home *** CD-ROM | disk | FTP | other *** search
/ InterCD 2000 September / september_2000.iso / intercd / root / ^Linux / cdrtools-1.10 / cdrecord / cdrecord.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-07-30  |  67.8 KB  |  2,718 lines

  1. /* @(#)cdrecord.c    1.106 00/07/30 Copyright 1995-2000 J. Schilling */
  2. #ifndef lint
  3. static    char sccsid[] =
  4.     "@(#)cdrecord.c    1.106 00/07/30 Copyright 1995-2000 J. Schilling";
  5. #endif
  6. /*
  7.  *    Record data on a CD/CVD-Recorder
  8.  *
  9.  *    Copyright (c) 1995-2000 J. Schilling
  10.  */
  11. /*
  12.  * This program is free software; you can redistribute it and/or modify
  13.  * it under the terms of the GNU General Public License as published by
  14.  * the Free Software Foundation; either version 2, or (at your option)
  15.  * any later version.
  16.  *
  17.  * This program is distributed in the hope that it will be useful,
  18.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  20.  * GNU General Public License for more details.
  21.  *
  22.  * You should have received a copy of the GNU General Public License
  23.  * along with this program; see the file COPYING.  If not, write to
  24.  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  25.  */
  26.  
  27. #include <mconfig.h>
  28. #include <stdio.h>
  29. #include <standard.h>
  30. #include <stdxlib.h>
  31. #include <fctldefs.h>
  32. #include <errno.h>
  33. #include <sys/types.h>
  34. #include <sys/time.h>
  35. #ifdef    HAVE_SYS_RESOURCE_H
  36. #include <sys/resource.h>    /* for rlimit */
  37. #endif
  38. #include <sys/stat.h>
  39. #include <statdefs.h>
  40. #include <unixstd.h>
  41. #ifdef    HAVE_SYS_MMAN_H
  42. #include <sys/mman.h>
  43. #endif
  44. #include <strdefs.h>
  45. #include <utypes.h>
  46. #include <intcvt.h>
  47. #include <signal.h>
  48. #include <schily.h>
  49.  
  50. #include <scg/scsireg.h>    /* XXX wegen SC_NOT_READY */
  51. #include <scg/scsitransp.h>
  52. #include <scg/scgcmd.h>        /* XXX fuer read_buffer */
  53. #include "scsi_scan.h"
  54.  
  55. #include "auheader.h"
  56. #include "cdrecord.h"
  57.  
  58. char    cdr_version[] = "1.10a02";
  59.  
  60. /*
  61.  * Map toc/track types into names.
  62.  */
  63. char    *toc2name[] = {
  64.         "CD-DA",
  65.         "CD-ROM",
  66.         "CD-ROM XA mode 1",
  67.         "CD-ROM XA mode 2",
  68.         "CD-I",
  69.         "Illegal toc type 5",
  70.         "Illegal toc type 6",
  71.         "Illegal toc type 7",
  72. };
  73.  
  74. /*
  75.  * Map sector types into names.
  76.  */
  77. char    *st2name[] = {
  78.         "Illegal sector type 0",
  79.         "CD-ROM mode 1",
  80.         "CD-ROM mode 2",
  81.         "Illegal sector type 3",
  82.         "CD-DA without preemphasis",
  83.         "CD-DA with preemphasis",
  84.         "Illegal sector type 6",
  85.         "Illegal sector type 7",
  86. };
  87.  
  88. /*
  89.  * Map data block types into names.
  90.  */
  91. char    *db2name[] = {
  92.         "Raw (audio)",
  93.         "Raw (audio) with P/Q sub channel",
  94.         "Raw (audio) with P/W sub channel",
  95.         "Raw (audio) with P/W raw sub channel",
  96.         "Reserved mode 4",
  97.         "Reserved mode 5",
  98.         "Reserved mode 6",
  99.         "Vendor unique mode 7",
  100.         "CD-ROM mode 1",
  101.         "CD-ROM mode 2",
  102.         "CD-ROM XA mode 1",
  103.         "CD-ROM XA mode 2 form 1",
  104.         "CD-ROM XA mode 2 form 2",
  105.         "CD-ROM XA mode 2 form 1/2/mix",
  106.         "Reserved mode 14",
  107.         "Vendor unique mode 15",
  108. };
  109.  
  110. int        debug;        /* print debug messages */
  111. LOCAL    int    scsi_verbose;    /* SCSI verbose flag */
  112. int        lverbose;    /* local verbose flag */
  113.  
  114. /*
  115.  * NOTICE:    You should not make BUF_SIZE more than
  116.  *        the buffer size of the CD-Recorder.
  117.  *
  118.  * Do not set BUF_SIZE to be more than 126 KBytes
  119.  * if you are running cdrecord on a sun4c machine.
  120.  *
  121.  * WARNING:    Philips CDD 521 dies if BUF_SIZE is to big.
  122.  */
  123. /*#define    BUF_SIZE    (126*1024)*/
  124. /*#define    BUF_SIZE    (100*1024)*/
  125. #define    BUF_SIZE    (63*1024)
  126. /*#define    BUF_SIZE    (56*1024)*/
  127.  
  128. char    *buf;            /* The transfer buffer */
  129. long    bufsize;        /* The size of the transfer buffer */
  130. int    data_secs_per_tr;    /* # of data secs per transfer */
  131. int    audio_secs_per_tr;    /* # of audio secs per transfer */
  132.  
  133. BOOL    isgui;
  134. int    didintr;
  135. char    *driveropts;
  136.  
  137. struct timeval    starttime;
  138. struct timeval    stoptime;
  139. struct timeval    fixtime;
  140.  
  141. static    long    fs = -1L;    /* fifo (ring buffer) size */
  142.  
  143. EXPORT    int     main        __PR((int ac, char **av));
  144. LOCAL    void    usage        __PR((int));
  145. LOCAL    void    blusage        __PR((int));
  146. LOCAL    void    intr        __PR((int sig));
  147. LOCAL    void    intfifo        __PR((int sig));
  148. LOCAL    void    exscsi        __PR((int excode, void *arg));
  149. LOCAL    void    excdr        __PR((int excode, void *arg));
  150. EXPORT    int    read_buf    __PR((int f, char *bp, int size));
  151. EXPORT    int    get_buf        __PR((int f, char **bpp, int size));
  152. LOCAL    int    write_track_data __PR((SCSI *scgp, cdr_t *, int , track_t *));
  153. EXPORT    int    pad_track    __PR((SCSI *scgp, cdr_t *dp, int track, track_t *trackp,
  154.                      long startsec, long amt,
  155.                      BOOL dolast, long *bytesp));
  156. EXPORT    int    write_buf    __PR((SCSI *scgp, cdr_t *dp, int track, track_t *trackp,
  157.                      char *bp, long startsec, long amt, int secsize,
  158.                      BOOL dolast, long *bytesp));
  159. LOCAL    void    printdata    __PR((int, track_t *));
  160. LOCAL    void    printaudio    __PR((int, track_t *));
  161. LOCAL    void    checkfile    __PR((int, track_t *));
  162. LOCAL    int    checkfiles    __PR((int, track_t *));
  163. LOCAL    void    setpregaps    __PR((int, track_t *));
  164. LOCAL    long    checktsize    __PR((int, track_t *));
  165. LOCAL    void    checksize    __PR((track_t *));
  166. LOCAL    BOOL    checkdsize    __PR((SCSI *scgp, cdr_t *dp, dstat_t *dsp, long tsize, int flags));
  167. LOCAL    void    raise_fdlim    __PR((void));
  168. LOCAL    void    gargs        __PR((int, char **, int *, track_t *, char **,
  169.                     int *, cdr_t **,
  170.                     int *, long *, int *, int *));
  171. LOCAL    void    set_trsizes    __PR((cdr_t *, int, track_t *));
  172. EXPORT    void    load_media    __PR((SCSI *scgp, cdr_t *, BOOL));
  173. EXPORT    void    unload_media    __PR((SCSI *scgp, cdr_t *, int));
  174. EXPORT    void    set_secsize    __PR((SCSI *scgp, int secsize));
  175. LOCAL    void    check_recovery    __PR((SCSI *scgp, cdr_t *, int));
  176.     void    audioread    __PR((SCSI *scgp, cdr_t *, int));
  177. LOCAL    void    print_msinfo    __PR((SCSI *scgp, cdr_t *));
  178. LOCAL    void    print_toc    __PR((SCSI *scgp, cdr_t *));
  179. LOCAL    void    print_track    __PR((int, long, struct msf *, int, int, int));
  180. LOCAL    void    prtimediff    __PR((const char *fmt,
  181.                     struct timeval *start,
  182.                     struct timeval *stop));
  183. #if !defined(HAVE_SYS_PRIOCNTL_H)
  184. LOCAL    int    rt_raisepri    __PR((int));
  185. #endif
  186. EXPORT    void    raisepri    __PR((int));
  187. LOCAL    void    wait_input    __PR((void));
  188. LOCAL    void    checkgui    __PR((void));
  189. LOCAL    char *    astoll        __PR((const char *s, Llong *ll));
  190. LOCAL    Llong    number        __PR((char* arg, int* retp));
  191. EXPORT    int    getnum        __PR((char* arg, long* valp));
  192. EXPORT    int    getllnum    __PR((char *arg, Llong* lvalp));
  193. LOCAL    int    getbltype    __PR((char* optstr, long *typep));
  194.  
  195. struct exargs {
  196.     SCSI    *scgp;
  197.     cdr_t    *dp;
  198.     int    old_secsize;
  199.     int    flags;
  200.     int    exflags;
  201. } exargs;
  202.  
  203. EXPORT int 
  204. main(ac, av)
  205.     int    ac;
  206.     char    *av[];
  207. {
  208.     char    *dev = NULL;
  209.     int    timeout = 40;    /* Set default timeout to 40s CW-7502 is slow*/
  210.     int    speed = 1;
  211.     long    flags = 0L;
  212.     int    toctype = -1;
  213.     int    blanktype = 0;
  214.     int    i;
  215.     int    tracks = 0;
  216.     int    trackno;
  217.     long    tsize;
  218.     track_t    track[MAX_TRACK+2];    /* Max tracks + track 0 + track AA */
  219.     cdr_t    *dp = (cdr_t *)0;
  220.     dstat_t    ds;
  221.     long    startsec = 0L;
  222.     int    errs = 0;
  223.     SCSI    *scgp;
  224.     char    errstr[80];
  225.  
  226. #ifdef __EMX__ 
  227.     /* This gives wildcard expansion with Non-Posix shells with EMX */ 
  228.     _wildcard(&ac, &av); 
  229. #endif 
  230.     save_args(ac, av);
  231.  
  232.     fillbytes(track, sizeof(track), '\0');
  233.     raise_fdlim();
  234.     gargs(ac, av, &tracks, track, &dev, &timeout, &dp, &speed, &flags,
  235.                             &toctype, &blanktype);
  236.     if (toctype < 0)
  237.         comerrno(EX_BAD, "Internal error: Bad TOC type.\n");
  238.  
  239.     /*
  240.      * Warning: you are not allowed to modify or to remove this
  241.      * version printing code!
  242.      */
  243. #ifdef    DRV_DVD
  244.     i = set_cdrcmds("mmc_dvd", (cdr_t **)NULL);
  245. #endif
  246.     if ((flags & F_MSINFO) == 0 || lverbose || flags & F_VERSION)
  247.         printf("Cdrecord%s %s (%s-%s-%s) Copyright (C) 1995-2000 J÷rg Schilling\n",
  248. #ifdef    DRV_DVD
  249.                                 i?"-ProDVD":"",
  250. #else
  251.                                 "",
  252. #endif
  253.                                 cdr_version,
  254.                                 HOST_CPU, HOST_VENDOR, HOST_OS);
  255.     if (flags & F_VERSION)
  256.         exit(0);
  257.  
  258.     checkgui();
  259.  
  260.     if (debug || lverbose) {
  261.         printf("TOC Type: %d = %s\n",
  262.             toctype, toc2name[toctype & TOC_MASK]);
  263.     }
  264.  
  265.     if ((flags & (F_MSINFO|F_TOC|F_PRATIP|F_FIX|F_VERSION|F_CHECKDRIVE|F_INQUIRY|F_SCANBUS|F_RESET)) == 0) {
  266.         /*
  267.          * Try to lock us im memory (will only work for root)
  268.          * but you need access to root anyway to use /dev/scg?
  269.          */
  270. #if defined(HAVE_MLOCKALL) || defined(_POSIX_MEMLOCK)
  271.         if (mlockall(MCL_CURRENT|MCL_FUTURE) < 0) {
  272.             errmsg("WARNING: Cannot do mlockall(2).\n");
  273.             errmsgno(EX_BAD, "WARNING: This causes a high risk for buffer underruns.\n");
  274.         }
  275. #endif
  276.  
  277.         raisepri(0); /* max priority */
  278.         init_fifo(fs);
  279.     }
  280.  
  281.     if ((flags & F_WAITI) != 0) {
  282.         if (lverbose)
  283.             printf("Waiting for data on stdin...\n");
  284.         wait_input();
  285.     }
  286.  
  287.     if ((scgp = scg_open(dev, errstr, sizeof(errstr),
  288.                 debug, (flags & F_MSINFO) == 0 || lverbose)) == (SCSI *)0) {
  289.             errmsg("%s%sCannot open SCSI driver.\n", errstr, errstr[0]?". ":"");
  290.             comerrno(EX_BAD, "For possible targets try 'cdrecord -scanbus'. Make sure you are root.\n");
  291.     }
  292.     scg_settimeout(scgp, timeout);
  293.     scgp->verbose = scsi_verbose;
  294.     scgp->debug = debug;
  295.     scgp->cap->c_bsize = 2048;
  296.  
  297.  
  298.     if ((flags & F_MSINFO) == 0 || lverbose) {
  299.         char    *vers;
  300.         char    *auth;
  301.  
  302.         /*
  303.          * Warning: you are not allowed to modify or to remove this 
  304.          * version checking code!
  305.          */
  306.         vers = scg_version(0, SCG_VERSION);
  307.         auth = scg_version(0, SCG_AUTHOR);
  308.         printf("Using libscg version '%s-%s'\n", auth, vers);
  309.         if (auth == 0 || strcmp("schily", auth) != 0) {
  310.             errmsgno(EX_BAD,
  311.             "Warning: using inofficial version of libscg (%s-%s '%s').\n",
  312.                 auth, vers, scg_version(0, SCG_SCCS_ID));
  313.         }
  314.  
  315.         vers = scg_version(scgp, SCG_VERSION);
  316.         auth = scg_version(scgp, SCG_AUTHOR);
  317.         if (lverbose > 1)
  318.             error("Using libscg transport code version '%s-%s'\n", auth, vers);
  319.         if (auth == 0 || strcmp("schily", auth) != 0) {
  320.             errmsgno(EX_BAD,
  321.             "Warning: using inofficial libscg transport code version (%s-%s '%s').\n",
  322.                 auth, vers, scg_version(scgp, SCG_SCCS_ID));
  323.         }
  324.     }
  325.     if (lverbose && driveropts)
  326.         printf("Driveropts: '%s'\n", driveropts);
  327.  
  328.     bufsize = scg_bufsize(scgp, BUF_SIZE);
  329.     if (debug)
  330.         error("SCSI buffer size: %ld\n", bufsize);
  331.     if ((buf = scg_getbuf(scgp, bufsize)) == NULL)
  332.         comerr("Cannot get SCSI I/O buffer.\n");
  333.  
  334.     if ((flags & F_SCANBUS) != 0) {
  335.         select_target(scgp);
  336.         exit(0);
  337.     }
  338.     if ((flags & F_RESET) != 0) {
  339.         scg_reset(scgp);
  340.         exit(0);
  341.     }
  342.     /*
  343.      * First try to check which type of SCSI device we
  344.      * have.
  345.      */
  346.     if (debug || lverbose)
  347.         printf("atapi: %d\n", scg_isatapi(scgp));
  348.     scgp->silent++;
  349.     test_unit_ready(scgp);    /* eat up unit attention */
  350.     scgp->silent--;
  351.     if (!do_inquiry(scgp, (flags & F_MSINFO) == 0 || lverbose)) {
  352.         errmsgno(EX_BAD, "Cannot do inquiry for CD/DVD-Recorder.\n");
  353.         if (unit_ready(scgp))
  354.             errmsgno(EX_BAD, "The unit seems to be hung and needs power cycling.\n");
  355.         exit(EX_BAD);
  356.     }
  357.  
  358.     if ((flags & F_PRCAP) != 0) {
  359.         print_capabilities(scgp);
  360.         exit(0);
  361.     }
  362.     if ((flags & F_INQUIRY) != 0)
  363.         exit(0);
  364.  
  365.     if (dp == (cdr_t *)NULL) {    /* No driver= option specified */
  366.         dp = get_cdrcmds(scgp);
  367.     } else if (!is_unknown_dev(scgp) && dp != get_cdrcmds(scgp)) {
  368.         errmsgno(EX_BAD, "WARNING: Trying to use other driver on known device.\n");
  369.     }
  370.  
  371.     if (!is_cddrive(scgp))
  372.         comerrno(EX_BAD, "Sorry, no CD/DVD-Drive found on this target.\n");
  373.     if (dp == (cdr_t *)0)
  374.         comerrno(EX_BAD, "Sorry, no supported CD/DVD-Recorder found on this target.\n");
  375.  
  376.     if (((flags & (F_MSINFO|F_TOC|F_LOAD|F_EJECT)) == 0 || tracks > 0) &&
  377.                     (dp->cdr_flags & CDR_ISREADER) != 0) {
  378.         comerrno(EX_BAD,
  379.         "Sorry, no CD/DVD-Recorder or unsupported CD/DVD-Recorder found on this target.\n");
  380.     }
  381.  
  382.     if ((*dp->cdr_attach)(scgp, dp) != 0)
  383.         comerrno(EX_BAD, "Cannot attach driver for CD/DVD-Recorder.\n");
  384.  
  385.     exargs.scgp       = scgp;
  386.     exargs.dp       = dp;
  387.     exargs.old_secsize = -1;
  388.     exargs.flags       = flags;
  389.  
  390.     if ((flags & F_MSINFO) == 0 || lverbose) {
  391.         printf("Using %s (%s).\n", dp->cdr_drtext, dp->cdr_drname);
  392.         printf("Driver flags   : ");
  393.         if ((dp->cdr_flags & CDR_SWABAUDIO) != 0)
  394.             printf("SWABAUDIO");
  395.         printf("\n");
  396.     }
  397.     scgp->silent++;
  398.     if ((debug || lverbose)) {
  399.         tsize = -1;
  400.         if ((*dp->cdr_buffer_cap)(scgp, &tsize, (long *)0) < 0 || tsize <= 0) {
  401.             if (read_buffer(scgp, buf, 4, 0) >= 0)
  402.                 tsize = a_to_u_4_byte(buf);
  403.         }
  404.         if (tsize > 0) {
  405.             printf("Drive buf size : %lu = %lu KB\n",
  406.                         tsize, tsize >> 10);
  407.         }
  408.     }
  409.     scgp->silent--;
  410.  
  411.     if (tracks > 0 && (debug || lverbose))
  412.         printf("FIFO size      : %lu = %lu KB\n", fs, fs >> 10);
  413.  
  414.     if ((flags & F_CHECKDRIVE) != 0)
  415.         exit(0);
  416.  
  417.     if (tracks == 0 && (flags & (F_FIX|F_BLANK)) == 0 && (flags & F_EJECT) != 0) {
  418.         /*
  419.          * Do not check if the unit is ready here to allow to open
  420.          * an empty unit too.
  421.          */
  422.         unload_media(scgp, dp, flags);
  423.         exit(0);
  424.     }
  425.  
  426.     flush();
  427.     if (tracks > 1)
  428.         sleep(2);    /* Let the user watch the inquiry messages */
  429.  
  430.     set_trsizes(dp, tracks, track);
  431.     setpregaps(tracks, track);
  432.     checkfiles(tracks, track);
  433.     tsize = checktsize(tracks, track);
  434. do_cue(tracks, track, 0);
  435.  
  436.     /*
  437.      * Is this the right place to do this ?
  438.      */
  439.     check_recovery(scgp, dp, flags);
  440.  
  441.     if ((flags & F_FORCE) == 0)
  442.         load_media(scgp, dp, TRUE);
  443.  
  444.     if ((flags & F_LOAD) != 0) {
  445.         scgp->silent++;            /* silently         */
  446.         scsi_prevent_removal(scgp, 0);    /* allow manual open */
  447.         scgp->silent--;            /* if load failed... */
  448.         exit(0);
  449.     }
  450.     exargs.old_secsize = sense_secsize(scgp, 1);
  451.     if (exargs.old_secsize < 0)
  452.         exargs.old_secsize = sense_secsize(scgp, 0);
  453.     if (debug)
  454.         printf("Current Secsize: %d\n", exargs.old_secsize);
  455.     scgp->silent++;
  456.     read_capacity(scgp);
  457.     scgp->silent--;
  458.     if (exargs.old_secsize < 0)
  459.         exargs.old_secsize = scgp->cap->c_bsize;
  460.     if (exargs.old_secsize != scgp->cap->c_bsize)
  461.         errmsgno(EX_BAD, "Warning: blockdesc secsize %d differs from cap secsize %d\n",
  462.                 exargs.old_secsize, scgp->cap->c_bsize);
  463.  
  464.     on_comerr(exscsi, &exargs);
  465.  
  466.     if (lverbose)
  467.         printf("Current Secsize: %d\n", exargs.old_secsize);
  468.  
  469.     if (exargs.old_secsize > 0 && exargs.old_secsize != 2048) {
  470.         /*
  471.          * Some drives (e.g. Plextor) don't like to write correctly
  472.          * in DAO mode if the sector size is set to 512 bytes.
  473.          * In addition, cdrecord -msinfo will not work properly
  474.          * if the sector size is not 2048 bytes.
  475.          */
  476.         set_secsize(scgp, 2048);
  477.     }
  478.  
  479. /*audioread(dp, flags);*/
  480. /*unload_media(scgp, dp, flags);*/
  481. /*return 0;*/
  482.     fillbytes(&ds, sizeof(ds), '\0');
  483.     if (flags & F_WRITE)
  484.         ds.ds_cdrflags = RF_WRITE;
  485.     if (flags & F_PRATIP) {
  486.         lverbose++;            /* XXX Hack */
  487.     }
  488.     if ((*dp->cdr_getdisktype)(scgp, dp, &ds) < 0) {
  489.         errmsgno(EX_BAD, "Cannot get disk type.\n");
  490.         exscsi(EX_BAD, &exargs);
  491.         if ((flags & F_FORCE) == 0)
  492.             exit(EX_BAD);
  493.     }
  494.     if (flags & F_PRATIP) {
  495.         lverbose--;            /* XXX Hack */
  496.         exscsi(0, &exargs);
  497.         exit(0);
  498.     }
  499.     /*
  500.      * The next actions should depend on the disk type.
  501.      */
  502.  
  503.     /*
  504.      * Dirty hack!
  505.      * At least MMC drives will not return the next writable
  506.      * address we expect when the drive's write mode is set
  507.      * to DAO/SAO. We need this address for mkisofs and thus
  508.      * it must be the first user accessible sector and not the
  509.      * first sector of the pregap. Set_speed_dummy() witha a
  510.      * 'speedp' f 0 sets the write mode to TAO on MMC drives.
  511.      *
  512.      * We set TAO unconditionally to make checkdsize() work
  513.      * currectly in DAO mode too.
  514.      */
  515.     scgp->silent++;
  516.     (*dp->cdr_set_speed_dummy)(scgp, 0, TRUE);
  517.     scgp->silent--;
  518.  
  519.     if (flags & F_MSINFO) {
  520.         print_msinfo(scgp, dp);
  521.         exscsi(0, &exargs);
  522.         exit(0);
  523.     }
  524.     if (flags & F_TOC) {
  525.         print_toc(scgp, dp);
  526.         exscsi(0, &exargs);
  527.         exit(0);
  528.     }
  529.  
  530. #ifdef    XXX
  531.     if ((*dp->cdr_check_session)() < 0) {
  532.         exscsi(EX_BAD, &exargs);
  533.         exit(EX_BAD);
  534.     }
  535. #endif
  536.     if (tsize == 0) {
  537.         if (tracks > 0) {
  538.             errmsgno(EX_BAD,
  539.             "WARNING: Track size unknown. Data may not fit on disk.\n");
  540.         }
  541.     } else if (!checkdsize(scgp, dp, &ds, tsize, flags)) {
  542.         exscsi(EX_BAD, &exargs);
  543.         exit(EX_BAD);
  544.     }
  545.     if (tracks > 0 && fs > 0l) {
  546.         /*
  547.          * Start the extra process needed for improved buffering.
  548.          */
  549.         if (!init_faio(tracks, track, bufsize))
  550.             fs = 0L;
  551.         else
  552.             on_comerr(excdr, &exargs);
  553.     }
  554.     if ((*dp->cdr_set_speed_dummy)(scgp, &speed, flags & F_DUMMY) < 0) {
  555.         errmsgno(EX_BAD, "Cannot set speed/dummy.\n");
  556.         excdr(EX_BAD, &exargs);
  557.         exit(EX_BAD);
  558.     }
  559.     if ((flags & (F_BLANK|F_FORCE)) == (F_BLANK|F_FORCE)) {
  560.         wait_unit_ready(scgp, 120);
  561.         scsi_blank(scgp, 0L, blanktype, FALSE);
  562.         excdr(0, &exargs);
  563.         exit(0);
  564.     }
  565.     /*
  566.      * Last chance to quit!
  567.      */
  568.     printf("Starting to write CD/DVD at speed %d in %s mode for %s session.\n",
  569.         speed,
  570.         (flags & F_DUMMY) ? "dummy" : "write",
  571.         (flags & F_MULTI) ? "multi" : "single");
  572.     printf("Last chance to quit, starting %s write in 9 seconds.",
  573.         (flags & F_DUMMY)?"dummy":"real");
  574.     flush();
  575.     signal(SIGINT, intr);
  576.     for (i=9; --i > 0;) {
  577.         sleep(1);
  578.         if (didintr) {
  579.             printf("\n");
  580.             goto restore_it;
  581.         }
  582.         printf("\b\b\b\b\b\b\b\b\b\b%d seconds.", i);
  583.         flush();
  584.     }
  585.     signal(SIGINT, SIG_DFL);
  586.     signal(SIGINT, intfifo);
  587.     signal(SIGTERM, intfifo);
  588.     printf("\n");
  589.     if (tracks > 0 && fs > 0l) {
  590.         /*
  591.          * Wait for the read-buffer to become full.
  592.          * This should be take no extra time if the input is a file.
  593.          * If the input is a pipe (e.g. mkisofs) this can take a
  594.          * while. If mkisofs dumps core before it starts writing,
  595.          * we abort before the writing process started.
  596.          */
  597.         if (!await_faio()) {
  598.             errmsgno(EX_BAD, "Input buffer error, aborting.\n");
  599.             excdr(EX_BAD, &exargs);
  600.             exit(EX_BAD);
  601.         }
  602.     }
  603.     if (gettimeofday(&starttime, (struct timezone *)0) < 0)
  604.         errmsg("Cannot get start time\n");
  605.  
  606.     /*
  607.      * Blank the media if we were requested to do so
  608.      */
  609.     if (flags & F_BLANK) {
  610.         if ((*dp->cdr_blank)(scgp, 0L, blanktype) < 0) {
  611.             errmsgno(EX_BAD, "Cannot blank disk, aborting.\n");
  612.             excdr(EX_BAD, &exargs);
  613.             exit(EX_BAD);
  614.         }
  615.         if (gettimeofday(&fixtime, (struct timezone *)0) < 0)
  616.             errmsg("Cannot get blank time\n");
  617.         if (lverbose)
  618.             prtimediff("Blanking time: ", &starttime, &fixtime);
  619.  
  620.         if (!wait_unit_ready(scgp, 60) || tracks == 0) {
  621.             excdr(0, &exargs);
  622.             exit(0);
  623.         }
  624.         /*
  625.          * Reset start time so we will not see blanking time and
  626.          * writing time counted together.
  627.          */
  628.         if (gettimeofday(&starttime, (struct timezone *)0) < 0)
  629.             errmsg("Cannot get start time\n");
  630.     }
  631.     /*
  632.      * Get the number of the next recordable track.
  633.      */
  634.     scgp->silent++;
  635.     if (read_tochdr(scgp, dp, NULL, &trackno) < 0) {
  636.         trackno = 0;
  637.     }
  638.     scgp->silent--;
  639.     for (i = 1; i <= tracks; i++) {
  640.         track[i].trackno = i + trackno;
  641.     }
  642.     trackno++;
  643.     track[0].trackno = trackno;    /* XXX Hack for TEAC fixate */
  644.  
  645.     /*
  646.      * Now we actually start writing to the CD/DVD.
  647.      * XXX Check total size of the tracks and remaining size of disk.
  648.      */
  649.     if ((*dp->cdr_open_session)(scgp, dp, tracks, track, toctype, flags & F_MULTI) < 0) {
  650.         errmsgno(EX_BAD, "Cannot open new session.\n");
  651.         excdr(EX_BAD, &exargs);
  652.         exit(EX_BAD);
  653.     }
  654.     if ((flags & F_DUMMY) == 0 && dp->cdr_opc) {
  655.         if (debug || lverbose) {
  656.             printf("Performing OPC...\n");
  657.             flush();
  658.         }
  659.         if (dp->cdr_opc(scgp, NULL, 0, TRUE) < 0)
  660.             comerr("OPC failed.\n");
  661.     }
  662.  
  663.     /*
  664.      * As long as open_session() will do nothing but
  665.      * set up parameters, we may leave fix_it here.
  666.      * I case we have to add an open_session() for a drive
  667.      * that wants to do something that modifies the disk
  668.      * We have to think about a new solution.
  669.      */
  670.     if (flags & F_FIX)
  671.         goto fix_it;
  672.  
  673.     if (flags & F_SAO) {
  674.         if (debug || lverbose) {
  675.             printf("Sending CUE sheet...\n");
  676.             flush();
  677.         }
  678.         if ((*dp->cdr_send_cue)(scgp, tracks, track) < 0) {
  679.             errmsgno(EX_BAD, "Cannot send CUE sheet.\n");
  680.             excdr(EX_BAD, &exargs);
  681.             exit(EX_BAD);
  682.         }
  683.     }
  684.     if ((flags & F_SAO)) {
  685.         (*dp->cdr_next_wr_address)(scgp, 0, &track[0], &startsec);
  686.         if (startsec <= 0 && startsec != -150) {
  687.             errmsgno(EX_BAD, "WARNING: Drive returns wrong startsec (%d) using -150\n",
  688.                     startsec);
  689.             startsec = -150;
  690.         }
  691.  
  692.         if (debug)
  693.             printf("SAO startsec: %ld\n", startsec);
  694.  
  695.         for (i = 1; i <= tracks; i++) {
  696.             track[i].trackstart += startsec +150;
  697.         }
  698. #ifdef    XXX
  699.         if (debug || lverbose)
  700.             printf("Writing lead-in...\n");
  701.  
  702.         pad_track(scgp, dp, 1, &track[1], -150, 0,
  703.                     FALSE, 0);
  704. #endif
  705.     }
  706.     /*
  707.      * Need to set trackno to the real value from
  708.      * the current disk status.
  709.      */
  710.     for (i = 1; i <= tracks; i++, trackno++) {
  711.         startsec = 0L;
  712.  
  713.         /*
  714.          * trackno is the "real" track number while 'i' is a counter
  715.          * going from 1 to tracks.
  716.          */
  717.         if ((*dp->cdr_open_track)(scgp, dp, trackno, &track[i]) < 0) {
  718.             errs++;
  719.             break;
  720.         }
  721.  
  722.         if ((flags & F_SAO) == 0) {
  723.             if ((*dp->cdr_next_wr_address)(scgp, trackno, &track[i], &startsec) < 0) {
  724.                 errs++;
  725.                 break;
  726.             }
  727.             track[i].trackstart = startsec;
  728.         }
  729.         if (debug || lverbose) {
  730.             printf("Starting new track at sector: %ld\n",
  731.                         track[i].trackstart);
  732.             flush();
  733.         }
  734.         if (write_track_data(scgp, dp, trackno, &track[i]) < 0) {
  735.             errs++;
  736.             sleep(5);
  737.             request_sense(scgp);
  738.             (*dp->cdr_close_track)(scgp, trackno, &track[i]);
  739.             break;
  740.         }
  741.         if ((*dp->cdr_close_track)(scgp, trackno, &track[i]) < 0) {
  742.             /*
  743.              * Check for "Dummy blocks added" message first.
  744.              */
  745.             if (scg_sense_key(scgp) != SC_ILLEGAL_REQUEST ||
  746.                     scg_sense_code(scgp) != 0xB5) {
  747.                 errs++;
  748.                 break;
  749.             }
  750.         }
  751.     }
  752. fix_it:
  753.     if (gettimeofday(&stoptime, (struct timezone *)0) < 0)
  754.         errmsg("Cannot get stop time\n");
  755.     if (lverbose)
  756.         prtimediff("Writing  time: ", &starttime, &stoptime);
  757.  
  758.     if ((flags & F_NOFIX) == 0) {
  759.         if (lverbose) {
  760.             printf("Fixating...\n");
  761.             flush();
  762.         }
  763.         if ((*dp->cdr_fixate)(scgp, flags & F_MULTI, flags & F_DUMMY,
  764.                 toctype, tracks, track) < 0) {
  765.             /*
  766.              * Ignore fixating errors in dummy mode.
  767.              */
  768.             if ((flags & F_DUMMY) == 0)
  769.                 errs++;
  770.         }
  771.         if (gettimeofday(&fixtime, (struct timezone *)0) < 0)
  772.             errmsg("Cannot get fix time\n");
  773.         if (lverbose)
  774.             prtimediff("Fixating time: ", &stoptime, &fixtime);
  775.     }
  776.  
  777. restore_it:
  778.     /*
  779.      * Try to restore the old sector size and stop FIFO.
  780.      */
  781.     excdr(errs?-2:0, &exargs);
  782.     exit(errs?-2:0);
  783.     return (0);
  784. }
  785.  
  786. LOCAL void 
  787. usage(excode)
  788.     int excode;
  789. {
  790.     errmsgno(EX_BAD, "Usage: %s [options] track1...trackn\n",
  791.         get_progname());
  792.  
  793.     error("Options:\n");
  794.     error("\t-version    print version information and exit\n");
  795.     error("\t-v        increment general verbose level by one\n");
  796.     error("\t-V        increment SCSI command transport verbose level by one\n");
  797.     error("\t-debug        print additional debug messages\n");
  798.     error("\tdev=target    SCSI target to use as CD/DVD-Recorder\n");
  799.     error("\ttimeout=#    set the default SCSI command timeout to #.\n");
  800.     error("\tdriver=name    user supplied driver name, use with extreme care\n");
  801.     error("\tdriveropts=opt    a comma separated list of driver specific options\n");
  802.     error("\t-checkdrive    check if a driver for the drive is present\n");
  803.     error("\t-prcap        print drive capabilities for MMC compliant drives\n");
  804.     error("\t-inq        do an inquiry for the drive end exit\n");
  805.     error("\t-scanbus    scan the SCSI bus end exit\n");
  806.     error("\t-reset        reset the SCSI bus with the cdrecorder (if possible)\n");
  807.     error("\t-ignsize    ignore the known size of a medium (may cause problems)\n");
  808.     error("\t-useinfo    use *.inf files to overwrite audio options.\n");
  809.     error("\tspeed=#        set speed of drive\n");
  810.     error("\tblank=type    blank a CD-RW disc (see blank=help)\n");
  811. #ifdef    FIFO
  812.     error("\tfs=#        Set fifo size to # (0 to disable, default is %ld MB)\n",
  813.                             DEFAULT_FIFOSIZE/(1024*1024));
  814. #endif
  815.     error("\t-load        load the disk and exit (works only with tray loader)\n");
  816.     error("\t-eject        eject the disk after doing the work\n");
  817.     error("\t-dummy        do everything with laser turned off\n");
  818.     error("\t-msinfo        retrieve multi-session info for mkisofs >= 1.10\n");
  819.     error("\t-toc        retrieve and print TOC/PMA data\n");
  820.     error("\t-atip        retrieve and print ATIP data\n");
  821.     error("\t-multi        generate a TOC that allows multi session\n");
  822.     error("\t        In this case default track type is CD-ROM XA2\n");
  823.     error("\t-fix        fixate a corrupt or unfixated disk (generate a TOC)\n");
  824.     error("\t-nofix        do not fixate disk after writing tracks\n");
  825.     error("\t-waiti        wait until input is available before opening SCSI\n");
  826.     error("\t-force        force to continue on some errors to allow blanking bad disks\n");
  827.     error("\t-dao        Write disk in DAO mode. This option will be replaced in the future.\n");
  828.     error("\ttsize=#        Length of valid data in next track\n");
  829.     error("\tpadsize=#    Amount of padding for next track\n");
  830.     error("\tpregap=#    Amount of pre-gap sectors before next track\n");
  831.     error("\tdefpregap=#    Amount of pre-gap sectors for all but track #1\n");
  832.     error("\tmcn=text    Set the media catalog number for this CD to 'text'\n");
  833.     error("\tisrc=text    Set the ISRC number for the next track to 'text'\n");
  834.     error("\tindex=list    Set the index list for the next track to 'list'\n");
  835.  
  836.     error("\t-audio        Subsequent tracks are CD-DA audio tracks\n");
  837.     error("\t-data        Subsequent tracks are CD-ROM data mode 1 (default)\n");
  838.     error("\t-mode2        Subsequent tracks are CD-ROM data mode 2\n");
  839.     error("\t-xa1        Subsequent tracks are CD-ROM XA mode 1\n");
  840.     error("\t-xa2        Subsequent tracks are CD-ROM XA mode 2\n");
  841.     error("\t-cdi        Subsequent tracks are CDI tracks\n");
  842.     error("\t-isosize    Use iso9660 file system size for next data track\n");
  843.     error("\t-preemp        Audio tracks are mastered with 50/15 ╡s preemphasis\n");
  844.     error("\t-nopreemp    Audio tracks are mastered with no preemphasis (default)\n");
  845.     error("\t-pad        Pad data tracks with %d zeroed sectors\n", PAD_SECS);
  846.     error("\t        Pad audio tracks to a multiple of %d bytes\n", AUDIO_SEC_SIZE);
  847.     error("\t-nopad        Do not pad data tracks (default)\n");
  848.     error("\t-shorttrack    Subsequent tracks may be non Red Book < 4 seconds if in DAO mode\n");
  849.     error("\t-noshorttrack    Subsequent tracks must be >= 4 seconds\n");
  850.     error("\t-swab        Audio data source is byte-swapped (little-endian/Intel)\n");
  851.     error("The type of the first track is used for the toc type.\n");
  852.     error("Currently only form 1 tracks are supported.\n");
  853.     exit(excode);
  854. }
  855.  
  856. LOCAL void
  857. blusage(ret)
  858.     int    ret;
  859. {
  860.     error("Blanking options:\n");
  861.     error("\tall\t\tblank the entire disk\n");
  862.     error("\tdisc\t\tblank the entire disk\n");
  863.     error("\tdisk\t\tblank the entire disk\n");
  864.     error("\tfast\t\tminimally blank the entire disk (PMA, TOC, pregap)\n");
  865.     error("\tminimal\t\tminimally blank the entire disk (PMA, TOC, pregap)\n");
  866.     error("\ttrack\t\tblank a track\n");
  867.     error("\tunreserve\tunreserve a track\n");
  868.     error("\ttrtail\t\tblank a track tail\n");
  869.     error("\tunclose\t\tunclose last session\n");
  870.     error("\tsession\t\tblank last session\n");
  871.  
  872.     exit(ret);
  873.     /* NOTREACHED */
  874. }
  875.  
  876. LOCAL void
  877. intr(sig)
  878.     int    sig;
  879. {
  880.     sig = 0;    /* Fake usage */
  881.  
  882.     signal(SIGINT, intr);
  883.  
  884.     didintr++;
  885. }
  886.  
  887. LOCAL void
  888. intfifo(sig)
  889.     int    sig;
  890. {
  891.     excdr(sig, NULL);
  892.     exit(sig);
  893. }
  894.  
  895. LOCAL void
  896. exscsi(excode, arg)
  897.     int    excode;
  898.     void    *arg;
  899. {
  900.     struct exargs    *exp = (struct exargs *)arg;
  901.  
  902.     /*
  903.      * Try to restore the old sector size.
  904.      */
  905.     if (exp != NULL && exp->exflags == 0) {
  906.  
  907.         set_secsize(exp->scgp, exp->old_secsize);
  908.         unload_media(exp->scgp, exp->dp, exp->flags);
  909.  
  910.         exp->exflags++;    /* Make sure that it only get called once */
  911.     }
  912. }
  913.  
  914. LOCAL void
  915. excdr(excode, arg)
  916.     int    excode;
  917.     void    *arg;
  918. {
  919.     exscsi(excode, arg);
  920.  
  921. #ifdef    FIFO
  922.     kill_faio();
  923.     wait_faio();
  924.     if (debug || lverbose)
  925.         fifo_stats();
  926. #endif
  927. }
  928.  
  929. EXPORT int
  930. read_buf(f, bp, size)
  931.     int    f;
  932.     char    *bp;
  933.     int    size;
  934. {
  935.     char    *p = bp;
  936.     int    amount = 0;
  937.     int    n;
  938.  
  939.     do {
  940.         do {
  941.             n = read(f, p, size-amount);
  942.         } while (n < 0 && (errno == EAGAIN || errno == EINTR));
  943.         if (n < 0)
  944.             return (n);
  945.         amount += n;
  946.         p += n;
  947.  
  948.     } while (amount < size && n > 0);
  949.     return (amount);
  950. }
  951.  
  952. EXPORT int
  953. get_buf(f, bpp, size)
  954.     int    f;
  955.     char    **bpp;
  956.     int    size;
  957. {
  958.     if (fs > 0) {
  959. /*        return (faio_read_buf(f, *bpp, size));*/
  960.         return (faio_get_buf(f, bpp, size));
  961.     } else {
  962.         return (read_buf(f, *bpp, size));
  963.     }
  964. }
  965.  
  966. LOCAL int
  967. write_track_data(scgp, dp, track, trackp)
  968.     SCSI    *scgp;
  969.     cdr_t    *dp;
  970.     int    track;
  971.     track_t    *trackp;
  972. {
  973.     int    f;
  974.     int    isaudio;
  975.     long    startsec;
  976.     long    bytes_read = 0;
  977.     long    bytes    = 0;
  978.     long    savbytes = 0;
  979.     int    count;
  980.     long    tracksize;
  981.     int    secsize;
  982.     int    secspt;
  983.     int    bytespt;
  984.     int    bytes_to_read;
  985.     long    amount;
  986.     int    pad;
  987.     int    bswab;
  988.     BOOL    neednl    = FALSE;
  989.     BOOL    islast    = FALSE;
  990.     char    *bp    = buf;
  991. long bsize;
  992. long bfree;
  993. /*#define    BCAP*/
  994. #ifdef    BCAP
  995. int per;
  996. int oper = -1;
  997. #endif
  998.  
  999.     scgp->silent++;
  1000.     if (read_buff_cap(scgp, &bsize, &bfree) < 0)
  1001.         bsize = -1;
  1002.     scgp->silent--;
  1003.  
  1004.  
  1005.     if (is_packet(trackp))    /* XXX Ugly hack for now */
  1006.         return (write_packet_data(scgp, dp, track, trackp));
  1007.  
  1008.     f = trackp->f;
  1009.     isaudio = is_audio(trackp);
  1010.     tracksize = trackp->tracksize;
  1011.     startsec = trackp->trackstart;
  1012.  
  1013.     secsize = trackp->secsize;
  1014.     secspt = trackp->secspt;
  1015.     bytespt = secsize * secspt;
  1016.     
  1017.     pad = !isaudio && is_pad(trackp);    /* Pad only data tracks */
  1018.     bswab = isaudio && is_swab(trackp);    /* Swab only audio tracks */
  1019.  
  1020.     if (debug) {
  1021.         printf("secsize:%d secspt:%d bytespt:%d audio:%d pad:%d\n",
  1022.             secsize, secspt, bytespt, isaudio, pad);
  1023.     }
  1024.  
  1025.     if (lverbose) {
  1026.         if (tracksize > 0)
  1027.             printf("\rTrack %02d:   0 of %3ld MB written.",
  1028.                    track, tracksize >> 20);
  1029.         else
  1030.             printf("\rTrack %02d:   0 MB written.", track);
  1031.         flush();
  1032.         neednl = TRUE;
  1033.     }
  1034.  
  1035.     do {
  1036.         bytes_to_read = bytespt;
  1037.         if (tracksize > 0) {
  1038.             bytes_to_read = tracksize - bytes_read;
  1039.             if (bytes_to_read > bytespt)
  1040.                 bytes_to_read = bytespt;
  1041.         }
  1042.         count = get_buf(f, &bp, bytes_to_read);
  1043.  
  1044.         if (count < 0)
  1045.             comerr("read error on input file\n");
  1046.         if (count == 0)
  1047.             break;
  1048.         bytes_read += count;
  1049.         if (tracksize >= 0 && bytes_read >= tracksize) {
  1050.             count -= bytes_read - tracksize;
  1051.             /*
  1052.              * Paranoia: tracksize is known (trackp->tracksize >= 0)
  1053.              * At this point, trackp->padsize should alway be set
  1054.              * if the tracksize is less than 300 sectors.
  1055.              */
  1056.             if (trackp->padsize == 0 &&
  1057.                 (is_shorttrk(trackp) || (bytes_read/secsize) >= 300))
  1058.                 islast = TRUE;
  1059.         }
  1060.  
  1061.         if (bswab)
  1062.             swabbytes(bp, count);
  1063.  
  1064.         if (count < bytespt) {
  1065.             if (debug) {
  1066.                 printf("\nNOTICE: reducing block size for last record.\n");
  1067.                 neednl = FALSE;
  1068.             }
  1069.  
  1070.             if ((amount = count % secsize) != 0) {
  1071.                 amount = secsize - amount;
  1072.                 fillbytes(&bp[count], amount, '\0');
  1073.                 count += amount;
  1074.                 printf("\nWARNING: padding up to secsize.\n");
  1075.                 neednl = FALSE;
  1076.             }
  1077.             bytespt = count;
  1078.             secspt = count / secsize;
  1079.             /*
  1080.              * If tracksize is not known (trackp->tracksize < 0)
  1081.              * we may need to set trackp->padsize 
  1082.              * if the tracksize is less than 300 sectors.
  1083.              */
  1084.             if (trackp->padsize == 0 &&
  1085.                 (is_shorttrk(trackp) || (bytes_read/secsize) >= 300))
  1086.                 islast = TRUE;
  1087.         }
  1088.  
  1089. again:
  1090.         scgp->silent++;
  1091.         amount = (*dp->cdr_write_trackdata)(scgp, bp, startsec, bytespt, secspt, islast);
  1092.         scgp->silent--;
  1093.         if (amount < 0) {
  1094.             if (scsi_in_progress(scgp)) {
  1095.                 usleep(100000);
  1096.                 goto again;
  1097.             }
  1098.  
  1099.             printf("%swrite track data: error after %ld bytes\n",
  1100.                             neednl?"\n":"", bytes);
  1101.             return (-1);
  1102.         }
  1103.         bytes += amount;
  1104.         startsec += amount / secsize;
  1105.  
  1106.         if (lverbose && (bytes >= (savbytes + 0x100000))) {
  1107.             int    fper;
  1108.  
  1109.             printf("\rTrack %02d: %3ld", track, bytes >> 20);
  1110.             if (tracksize > 0)
  1111.                 printf(" of %3ld MB", tracksize >> 20);
  1112.             else
  1113.                 printf(" MB");
  1114.             printf(" written");
  1115.             fper = fifo_percent(TRUE);
  1116.             if (fper >= 0)
  1117.                 printf(" (fifo %3d%%)", fper);
  1118.             printf(".");
  1119.             savbytes = (bytes >> 20) << 20;
  1120.             flush();
  1121.             neednl = TRUE;
  1122.         }
  1123. #ifdef    BCAP
  1124.         if (bsize >= 0) {
  1125.             read_buff_cap(scgp, 0, &bfree);
  1126.             per = 100*(bsize - bfree) / bsize;
  1127.             if (per != oper)
  1128.                 printf("[buf %3d%%] %3ld %3ld\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b",
  1129.                     per, bsize >> 10, bfree >> 10);
  1130.             oper = per;
  1131.             flush();
  1132.         }
  1133. #endif
  1134.     } while (tracksize < 0 || bytes_read < tracksize);
  1135.  
  1136.     if (!is_shorttrk(trackp) && (bytes / secsize) < 300) {
  1137.         /*
  1138.          * If tracksize is not known (trackp->tracksize < 0) or 
  1139.          * for some strange reason we did not set padsize properly
  1140.          * we may need to modify trackp->padsize if
  1141.          * tracksize+padsize is less than 300 sectors.
  1142.          */
  1143.         amount = roundup(trackp->padsize, secsize);
  1144.         if (((bytes+amount) / secsize) < 300)
  1145.             trackp->padsize = 300 * secsize - bytes;
  1146.     }
  1147.     if (trackp->padsize) {
  1148.         if (neednl) {
  1149.             printf("\n");
  1150.             neednl = FALSE;
  1151.         }
  1152.         if ((trackp->padsize >> 20) > 0) {
  1153.             neednl = TRUE;
  1154.         } else if (lverbose) {
  1155.             printf("Track %02d: writing %3ld KB of pad data.\n",
  1156.                         track, trackp->padsize >> 10);
  1157.             neednl = FALSE;
  1158.         }
  1159.         pad_track(scgp, dp, track, trackp, startsec, trackp->padsize,
  1160.                     TRUE, &amount);
  1161.         bytes += amount;
  1162.         startsec += amount / secsize;
  1163.     }
  1164.     printf("%sTrack %02d: Total bytes read/written: %ld/%ld (%ld sectors).\n",
  1165.            neednl?"\n":"", track, bytes_read, bytes, bytes/secsize);
  1166.     flush();
  1167.     return 0;
  1168. }
  1169.  
  1170. EXPORT int
  1171. pad_track(scgp, dp, track, trackp, startsec, amt, dolast, bytesp)
  1172.     SCSI    *scgp;
  1173.     cdr_t    *dp;
  1174.     int    track;
  1175.     track_t    *trackp;
  1176.     long    startsec;
  1177.     long    amt;
  1178.     BOOL    dolast;
  1179.     long    *bytesp;
  1180. {
  1181.     long    bytes    = 0;
  1182.     long    savbytes = 0;
  1183.     int    secsize;
  1184.     int    secspt;
  1185.     int    bytespt;
  1186.     int    amount;
  1187.     BOOL    neednl    = FALSE;
  1188.     BOOL    islast    = FALSE;
  1189.  
  1190.     secsize = trackp->secsize;
  1191.     secspt = trackp->secspt;
  1192.     bytespt = secsize * secspt;
  1193.     
  1194.     fillbytes(buf, bytespt, '\0');
  1195.  
  1196.     if ((amt >> 20) > 0) {
  1197.         printf("\rTrack %02d:   0 of %3ld MB pad written.",
  1198.                         track, amt >> 20);
  1199.         flush();
  1200.     }
  1201.     do {
  1202.         if (amt < bytespt) {
  1203.             bytespt = roundup(amt, secsize);
  1204.             secspt = bytespt / secsize;    
  1205.         }
  1206.         if (dolast && (amt - bytespt) <= 0)
  1207.             islast = TRUE;
  1208.  
  1209. again:
  1210.         scgp->silent++;
  1211.         amount = (*dp->cdr_write_trackdata)(scgp, buf, startsec, bytespt, secspt, islast);
  1212.         scgp->silent--;
  1213.         if (amount < 0) {
  1214.             if (scsi_in_progress(scgp)) {
  1215.                 usleep(100000);
  1216.                 goto again;
  1217.             }
  1218.  
  1219.             printf("%swrite track pad data: error after %ld bytes\n",
  1220.                             neednl?"\n":"", bytes);
  1221.             if (bytesp)
  1222.                 *bytesp = bytes;
  1223. read_buff_cap(scgp, 0, 0);
  1224.             return (-1);
  1225.         }
  1226.         amt -= amount;
  1227.         bytes += amount;
  1228.         startsec += amount / secsize;
  1229.  
  1230.         if (lverbose && (bytes >= (savbytes + 0x100000))) {
  1231.             printf("\rTrack %02d: %3ld", track, bytes >> 20);
  1232.             savbytes = (bytes >> 20) << 20;
  1233.             flush();
  1234.             neednl = TRUE;
  1235.         }
  1236.     } while (amt > 0);
  1237.  
  1238.     if (bytesp)
  1239.         *bytesp = bytes;
  1240.     return (bytes);
  1241. }
  1242.  
  1243. #ifdef    USE_WRITE_BUF
  1244. EXPORT int
  1245. write_buf(scgp, dp, track, trackp, bp, startsec, amt, secsize, dolast, bytesp)
  1246.     SCSI    *scgp;
  1247.     cdr_t    *dp;
  1248.     int    track;
  1249.     track_t    *trackp;
  1250.     char    *bp;
  1251.     long    startsec;
  1252.     long    amt;
  1253.     int    secsize;
  1254.     BOOL    dolast;
  1255.     long    *bytesp;
  1256. {
  1257.     long    bytes    = 0;
  1258.     long    savbytes = 0;
  1259. /*    int    secsize;*/
  1260.     int    secspt;
  1261.     int    bytespt;
  1262.     int    amount;
  1263.     BOOL    neednl    = FALSE;
  1264.     BOOL    islast    = FALSE;
  1265.  
  1266. /*    secsize = trackp->secsize;*/
  1267. /*    secspt = trackp->secspt;*/
  1268.  
  1269.     secspt = bufsize/secsize;
  1270.     secspt = min(255, secspt);
  1271.     bytespt = secsize * secspt;
  1272.     
  1273. /*    fillbytes(buf, bytespt, '\0');*/
  1274.  
  1275.     if ((amt >> 20) > 0) {
  1276.         printf("\rTrack %02d:   0 of %3ld MB pad written.",
  1277.                         track, amt >> 20);
  1278.         flush();
  1279.     }
  1280.     do {
  1281.         if (amt < bytespt) {
  1282.             bytespt = roundup(amt, secsize);
  1283.             secspt = bytespt / secsize;    
  1284.         }
  1285.         if (dolast && (amt - bytespt) <= 0)
  1286.             islast = TRUE;
  1287.  
  1288.         amount = (*dp->cdr_write_trackdata)(scgp, bp, startsec, bytespt, secspt, islast);
  1289.         if (amount < 0) {
  1290.             printf("%swrite track data: error after %ld bytes\n",
  1291.                             neednl?"\n":"", bytes);
  1292.             if (bytesp)
  1293.                 *bytesp = bytes;
  1294. read_buff_cap(scgp, 0, 0);
  1295.             return (-1);
  1296.         }
  1297.         amt -= amount;
  1298.         bytes += amount;
  1299.         startsec += amount / secsize;
  1300.  
  1301.         if (lverbose && (bytes >= (savbytes + 0x100000))) {
  1302.             printf("\rTrack %02d: %3ld", track, bytes >> 20);
  1303.             savbytes = (bytes >> 20) << 20;
  1304.             flush();
  1305.             neednl = TRUE;
  1306.         }
  1307.     } while (amt > 0);
  1308.  
  1309.     if (bytesp)
  1310.         *bytesp = bytes;
  1311.     return (bytes);
  1312. }
  1313. #endif    /* USE_WRITE_BUF */
  1314.  
  1315. LOCAL void
  1316. printdata(track, trackp)
  1317.     int    track;
  1318.     track_t    *trackp;
  1319. {
  1320.     if (trackp->tracksize >= 0) {
  1321.         printf("Track %02d: data  %3ld MB        ",
  1322.                     track, trackp->tracksize >> 20);
  1323.     } else {
  1324.         printf("Track %02d: data  unknown length",
  1325.                     track);
  1326.     }
  1327.     if (trackp->padsize > 0) {
  1328.         if ((trackp->padsize >> 20) > 0)
  1329.             printf(" padsize: %3ld MB", trackp->padsize >> 20);
  1330.         else
  1331.             printf(" padsize: %3ld KB", trackp->padsize >> 10);
  1332.     }
  1333.     if (trackp->pregapsize != 150) {
  1334.         printf(" pregapsize: %3ld", trackp->pregapsize);
  1335.     }
  1336.     printf("\n");
  1337. }
  1338.  
  1339. LOCAL void
  1340. printaudio(track, trackp)
  1341.     int    track;
  1342.     track_t    *trackp;
  1343. {
  1344.     if (trackp->tracksize >= 0) {
  1345.         printf("Track %02d: audio %3ld MB (%02d:%02d.%02d) %spreemp%s%s",
  1346.             track, trackp->tracksize >> 20,
  1347.             minutes(trackp->tracksize),
  1348.             seconds(trackp->tracksize),
  1349.             hseconds(trackp->tracksize),
  1350.             is_preemp(trackp) ? "" : "no ",
  1351.             is_swab(trackp) ? " swab":"",
  1352.             ((trackp->tracksize < 300L*trackp->secsize) ||
  1353.             (trackp->tracksize % trackp->secsize)) &&
  1354.             is_pad(trackp) ? " pad" : "");
  1355.     } else {
  1356.         printf("Track %02d: audio unknown length    %spreemp%s%s",
  1357.             track, is_preemp(trackp) ? "" : "no ",
  1358.             is_swab(trackp) ? " swab":"",
  1359.             (trackp->tracksize % trackp->secsize) && is_pad(trackp) ? " pad" : "");
  1360.     }
  1361.     if (trackp->padsize > 0) {
  1362.         if ((trackp->padsize >> 20) > 0)
  1363.             printf(" padsize: %3ld MB", trackp->padsize >> 20);
  1364.         else
  1365.             printf(" padsize: %3ld KB", trackp->padsize >> 10);
  1366.         printf(" (%02d:%02d.%02d)",
  1367.             minutes(trackp->padsize),
  1368.             seconds(trackp->padsize),
  1369.             hseconds(trackp->padsize));
  1370.     }
  1371.     if (trackp->pregapsize != 150) {
  1372.         printf(" pregapsize: %3ld", trackp->pregapsize);
  1373.     }
  1374.     printf("\n");
  1375. }
  1376.  
  1377. LOCAL void
  1378. checkfile(track, trackp)
  1379.     int    track;
  1380.     track_t    *trackp;
  1381. {
  1382.     if (trackp->tracksize > 0 &&
  1383.             is_audio(trackp) &&
  1384.             ( (!is_shorttrk(trackp) &&
  1385.               (trackp->tracksize < 300L*trackp->secsize)) ||
  1386.             (trackp->tracksize % trackp->secsize)) &&
  1387.                         !is_pad(trackp)) {
  1388.         errmsgno(EX_BAD, "Bad audio track size %ld for track %02d.\n",
  1389.                 trackp->tracksize, track);
  1390.         errmsgno(EX_BAD, "Audio tracks must be at least %ld bytes and a multiple of %d.\n",
  1391.                 300L*trackp->secsize, trackp->secsize);
  1392.         comerrno(EX_BAD, "See -pad option.\n");
  1393.     }
  1394.     
  1395.     if (!lverbose)
  1396.         return;
  1397.  
  1398.     if (is_audio(trackp))
  1399.         printaudio(track, trackp);
  1400.     else
  1401.         printdata(track, trackp);
  1402. }
  1403.  
  1404. LOCAL int
  1405. checkfiles(tracks, trackp)
  1406.     int    tracks;
  1407.     track_t    *trackp;
  1408. {
  1409.     int    i;
  1410.     int    isaudio = 1;
  1411.  
  1412.     for (i = 1; i <= tracks; i++) {
  1413.         if (!is_audio(&trackp[i]))
  1414.             isaudio = 0;
  1415.         checkfile(i, &trackp[i]);
  1416.     }
  1417.     return (isaudio);
  1418. }
  1419.  
  1420. LOCAL void
  1421. setpregaps(tracks, trackp)
  1422.     int    tracks;
  1423.     track_t    *trackp;
  1424. {
  1425.     int    i;
  1426.     int    sectype;
  1427.     track_t    *tp;
  1428.  
  1429.     /*
  1430.      * Set some values for track 0 (the lead-in)
  1431.      * XXX There should be a better place to do this.
  1432.      */
  1433.     sectype = trackp[1].sectype;
  1434.     trackp[0].sectype = sectype;
  1435.     trackp[0].dbtype = trackp[1].dbtype;
  1436.  
  1437.     for (i = 1; i <= tracks; i++) {
  1438.         tp = &trackp[i];
  1439.         if (tp->pregapsize == -1L) {
  1440.             tp->pregapsize = 150;        /* Default Pre GAP */
  1441.             if (sectype != tp->sectype) {
  1442.                 tp->pregapsize = 255;    /* Pre GAP is 255 */
  1443.                 tp->flags &= ~TI_PREGAP;
  1444.             }
  1445.         }
  1446.         sectype = tp->sectype;            /* Save old sectype */
  1447.     }
  1448.     /*
  1449.      * Set some values for track 0xAA (the lead-out)
  1450.      * XXX There should be a better place to do this.
  1451.      */
  1452.     trackp[tracks+1].sectype = sectype;
  1453.     trackp[tracks+1].dbtype = trackp[tracks].dbtype;
  1454. }
  1455.  
  1456. LOCAL long
  1457. checktsize(tracks, trackp)
  1458.     int    tracks;
  1459.     track_t    *trackp;
  1460. {
  1461.     int    i;
  1462.     long    curr;
  1463.     long    total = -150;
  1464.     Ullong    btotal;
  1465.     track_t    *tp;
  1466.  
  1467.     for (i = 1; i <= tracks; i++) {
  1468.         tp = &trackp[i];
  1469.         if (!is_pregap(tp))
  1470.             total += tp->pregapsize;
  1471.  
  1472.         if (lverbose > 1) {
  1473.             printf("track: %d start: %ld pregap: %ld\n",
  1474.                     i, total, tp->pregapsize);
  1475.         }
  1476.         tp->trackstart = total;
  1477.         if (tp->tracksize >= 0) {
  1478.             curr = (tp->tracksize + (tp->secsize-1)) / tp->secsize;
  1479.             curr += (tp->padsize + (tp->secsize-1)) / tp->secsize;
  1480.             /*
  1481.              * Minimum track size is 4s
  1482.              */
  1483.             if (!is_shorttrk(tp) && curr < 300)
  1484.                 curr = 300;
  1485.             if (is_tao(tp) && !is_audio(tp)) {
  1486.                 curr += 2;
  1487.             }
  1488.             total += curr;
  1489.         }
  1490.     }
  1491.     tp = &trackp[i];
  1492.     tp->trackstart = total;
  1493.     if (!lverbose)
  1494.         return (total);
  1495.  
  1496.     btotal = (Ullong)total * 2352;
  1497. /* XXX Sector Size ??? */
  1498.     if (tracks > 0) {
  1499.         printf("Total size:     %3lu MB (%02d:%02d.%02d) = %ld sectors\n",
  1500.             (Ulong)(btotal >> 20),
  1501.             minutes(btotal),
  1502.             seconds(btotal),
  1503.             hseconds(btotal), total);
  1504.         btotal += 150 * 2352;
  1505.         printf("Lout start:     %3lu MB (%02d:%02d/%02d) = %ld sectors\n",
  1506.             (Ulong)(btotal >> 20),
  1507.             minutes(btotal),
  1508.             seconds(btotal),
  1509.             frames(btotal), total);
  1510.     }
  1511.     return (total);
  1512. }
  1513.  
  1514. LOCAL void
  1515. checksize(trackp)
  1516.     track_t    *trackp;
  1517. {
  1518.     struct stat    st;
  1519.  
  1520.     /*
  1521.      * If the current input file is a regular file and
  1522.      * 'padsize=' has not been specified,
  1523.      * use fstat() or file parser to get the size of the file.
  1524.      */
  1525.     if (trackp->tracksize < 0 && (trackp->flags & TI_ISOSIZE) != 0) {
  1526.         trackp->tracksize = isosize(trackp->f);
  1527.     }
  1528.     if (trackp->tracksize < 0 && (trackp->flags & TI_NOAUHDR) == 0) {
  1529.         trackp->tracksize = ausize(trackp->f);
  1530.     }
  1531.     if (trackp->tracksize < 0 && (trackp->flags & TI_NOAUHDR) == 0) {
  1532.         trackp->tracksize = wavsize(trackp->f);
  1533.         if (trackp->tracksize > 0)    /* Force little endian input */
  1534.             trackp->flags |= TI_SWAB;
  1535.     }
  1536.     if (trackp->tracksize == AU_BAD_CODING) {
  1537.         comerrno(EX_BAD, "Inappropriate audio coding in '%s'.\n",
  1538.                             trackp->filename);
  1539.     }
  1540.     if (trackp->tracksize < 0 &&
  1541.             fstat(trackp->f, &st) >= 0 && S_ISREG(st.st_mode)) {
  1542.         trackp->tracksize = st.st_size;
  1543.     }
  1544. }
  1545.  
  1546. LOCAL BOOL
  1547. checkdsize(scgp, dp, dsp, tsize, flags)
  1548.     SCSI    *scgp;
  1549.     cdr_t    *dp;
  1550.     dstat_t    *dsp;
  1551.     long    tsize;
  1552.     int    flags;
  1553. {
  1554.     long    startsec = 0L;
  1555.     long    endsec = 0L;
  1556.  
  1557.     scgp->silent++;
  1558.     (*dp->cdr_next_wr_address)(scgp, /*i*/ 0, (track_t *)0, &startsec);
  1559.     scgp->silent--;
  1560.  
  1561.     /*
  1562.      * This only should happen when the drive is currently in DAO mode.
  1563.      * We rely on the drive being in TAO mode, a negative value for
  1564.      * startsec is not correct here it may be caused by bad firmware or
  1565.      * by a drive in DAO mode. In DAO mode the drive will report the
  1566.      * pre-gap as part of the writable area.
  1567.      */
  1568.     if (startsec < 0)
  1569.         startsec = 0;
  1570.  
  1571.     /*
  1572.      * Size limitations for CD's:
  1573.      *
  1574.      *        404850 == 90 min    Red book calls this the
  1575.      *                    first negative time
  1576.      *                    allows lead out start up to
  1577.      *                    block 404700
  1578.      *
  1579.      *        449850 == 100 min    This is the first time that
  1580.      *                    is no more representable
  1581.      *                    in a two digit BCD number.
  1582.      *                    allows lead out start up to
  1583.      *                    block 449700
  1584.      */
  1585.  
  1586.     endsec = startsec + tsize;
  1587.  
  1588.     if (dsp->ds_maxblocks > 0) {
  1589.         if (lverbose)
  1590.             printf("Blocks total: %ld Blocks current: %ld Blocks remaining: %ld\n",
  1591.                     dsp->ds_maxblocks,
  1592.                     dsp->ds_maxblocks - startsec,
  1593.                     dsp->ds_maxblocks - endsec);
  1594.  
  1595.         if (endsec > dsp->ds_maxblocks) {
  1596.             errmsgno(EX_BAD,
  1597.             "WARNING: Data may not fit on current disk.\n");
  1598.  
  1599.             /* XXX Check for flags & CDR_NO_LOLIMIT */
  1600. /*            goto toolarge;*/
  1601.         }
  1602.         if (lverbose && dsp->ds_maxrblocks > 0)
  1603.             printf("RBlocks total: %ld RBlocks current: %ld RBlocks remaining: %ld\n",
  1604.                     dsp->ds_maxrblocks,
  1605.                     dsp->ds_maxrblocks - startsec,
  1606.                     dsp->ds_maxrblocks - endsec);
  1607.         if (dsp->ds_maxrblocks > 0 && endsec > dsp->ds_maxrblocks) {
  1608.             errmsgno(EX_BAD,
  1609.             "Data does not fit on current disk.\n");
  1610.             goto toolarge;
  1611.         }
  1612.         if ((endsec > 404700) ||
  1613.             (dsp->ds_maxrblocks > 404700 && 449850 > dsp->ds_maxrblocks)) {
  1614.             /*
  1615.              * Assume that this must be a CD and not a DVD.
  1616.              * So this is a non Red Book compliant CD with a
  1617.              * capacity between 90 and 99 minutes.
  1618.              */
  1619.             if (dsp->ds_maxrblocks > 404700)
  1620.                 printf("RedBook total: %ld RedBook current: %ld RedBook remaining: %ld\n",
  1621.                     404700L,
  1622.                     404700L - startsec,
  1623.                     404700L - endsec);
  1624.             if (endsec > 404700) {
  1625.                 if ((flags & (F_IGNSIZE|F_FORCE)) == 0)
  1626.                     errmsgno(EX_BAD,
  1627.                     "Notice: Most recorders cannot write CD's >= 90 minutes.\n");
  1628.                     errmsgno(EX_BAD,
  1629.                     "Notice: Use -ignsize option to allow >= 90 minutes.\n");
  1630.                 goto toolarge;
  1631.             }
  1632.         }
  1633.     } else {
  1634.         if (endsec >= (405000-300)) {            /*<90 min disk*/
  1635.             errmsgno(EX_BAD,
  1636.                 "Data will not fit on any disk.\n");
  1637.             goto toolarge;
  1638.         } else if (endsec >= (333000-150)) {        /* 74 min disk*/
  1639.             errmsgno(EX_BAD,
  1640.             "WARNING: Data may not fit on standard 74min disk.\n");
  1641.         }
  1642.     }
  1643.     return (TRUE);
  1644. toolarge:
  1645.     if (dsp->ds_maxblocks < 449850) {
  1646.         /*
  1647.          * Assume that this must be a CD and not a DVD.
  1648.          */
  1649.         if (endsec > 449700) {
  1650.             errmsgno(EX_BAD, "Cannot write CD's >= 100 minutes.\n");
  1651.             return (FALSE);
  1652.         }
  1653.     }
  1654.     if ((flags & (F_IGNSIZE|F_FORCE)) != 0)
  1655.         return (TRUE);
  1656.     return (FALSE);
  1657. }
  1658.  
  1659. LOCAL void
  1660. raise_fdlim()
  1661. {
  1662. #ifdef    RLIMIT_NOFILE
  1663.  
  1664.     struct rlimit    rlim;
  1665.  
  1666.     /*
  1667.      * Set max # of file descriptors to be able to hold all files open
  1668.      */
  1669.     getrlimit(RLIMIT_NOFILE, &rlim);
  1670.     rlim.rlim_cur = MAX_TRACK + 10;
  1671.     if (rlim.rlim_cur > rlim.rlim_max)
  1672.         errmsgno(EX_BAD,
  1673.             "warning: low file descriptor limit (%ld)\n",
  1674.                             rlim.rlim_max);
  1675.     setrlimit(RLIMIT_NOFILE, &rlim);
  1676.  
  1677. #endif    /* RLIMIT_NOFILE */
  1678. }
  1679.  
  1680. char    *opts =
  1681. "help,version,checkdrive,prcap,inq,scanbus,reset,ignsize,useinfo,dev*,timeout#,driver*,driveropts*,tsize&,padsize&,pregap&,defpregap&,speed#,load,eject,dummy,msinfo,toc,atip,multi,fix,nofix,waiti,debug,v+,V+,audio,data,mode2,xa1,xa2,cdi,isosize,nopreemp,preemp,nopad,pad,swab,fs&,blank&,pktsize#,packet,noclose,force,dao,scms,isrc*,mcn*,index*,shorttrack,noshorttrack";
  1682.  
  1683. LOCAL void
  1684. gargs(ac, av, tracksp, trackp, devp, timeoutp, dpp, speedp, flagsp, toctypep, blankp)
  1685.     int    ac;
  1686.     char    **av;
  1687.     int    *tracksp;
  1688.     track_t    *trackp;
  1689.     cdr_t    **dpp;
  1690.     char    **devp;
  1691.     int    *timeoutp;
  1692.     int    *speedp;
  1693.     long    *flagsp;
  1694.     int    *toctypep;
  1695.     int    *blankp;
  1696. {
  1697.     int    cac;
  1698.     char    * const*cav;
  1699.     char    *driver = NULL;
  1700.     char    *dev = NULL;
  1701.     char    *isrc = NULL;
  1702.     char    *mcn = NULL;
  1703.     char    *tindex = NULL;
  1704.     long    bltype = -1;
  1705.     Llong    tracksize;
  1706.     Llong    padsize;
  1707.     long    pregapsize;
  1708.     long    defpregap = -1L;
  1709.     long    secsize;
  1710.     int    pktsize;
  1711.     int    speed = -1;
  1712.     int    help = 0;
  1713.     int    version = 0;
  1714.     int    checkdrive = 0;
  1715.     int    prcap = 0;
  1716.     int    inq = 0;
  1717.     int    scanbus = 0;
  1718.     int    reset = 0;
  1719.     int    ignsize = 0;
  1720.     int    useinfo = 0;
  1721.     int    load = 0;
  1722.     int    eject = 0;
  1723.     int    dummy = 0;
  1724.     int    msinfo = 0;
  1725.     int    toc = 0;
  1726.     int    atip = 0;
  1727.     int    multi = 0;
  1728.     int    fix = 0;
  1729.     int    nofix = 0;
  1730.     int    waiti = 0;
  1731.     int    audio;
  1732.     int    autoaudio = 0;
  1733.     int    data;
  1734.     int    mode2;
  1735.     int    xa1;
  1736.     int    xa2;
  1737.     int    cdi;
  1738.     int    isize;
  1739.     int    ispacket = 0;
  1740.     int    noclose = 0;
  1741.     int    force = 0;
  1742.     int    dao = 0;
  1743.     int    scms = 0;
  1744.     int    preemp = 0;
  1745.     int    nopreemp;
  1746.     int    pad = 0;
  1747.     int    bswab = 0;
  1748.     int    nopad;
  1749.     int    shorttrack = 0;
  1750.     int    noshorttrack;
  1751.     int    flags;
  1752.     int    tracks = *tracksp;
  1753.     int    tracktype = TOC_ROM;
  1754.     int    sectype = ST_ROM_MODE1;
  1755.     int    dbtype = DB_ROM_MODE1;
  1756.     int    got_track;
  1757.  
  1758.     trackp[0].flags |= TI_TAO;
  1759.     trackp[1].pregapsize = -1;
  1760.     *flagsp |= F_WRITE;
  1761.  
  1762.     cac = --ac;
  1763.     cav = ++av;
  1764.     for (;; cac--, cav++) {
  1765.         tracksize = (Llong)-1L;
  1766.         padsize = (Llong)0L;
  1767.         pregapsize = defpregap;
  1768.         audio = data = mode2 = xa1 = xa2 = cdi = 0;
  1769.         isize = nopreemp = nopad = noshorttrack = 0;
  1770.         pktsize = 0;
  1771.         isrc = NULL;
  1772.         tindex = NULL;
  1773.         if (getargs(&cac, &cav, opts,
  1774.                 &help, &version, &checkdrive, &prcap,
  1775.                 &inq, &scanbus, &reset, &ignsize,
  1776.                 &useinfo,
  1777.                 devp, timeoutp, &driver, &driveropts,
  1778.                 getllnum, &tracksize,
  1779.                 getllnum, &padsize,
  1780.                 getnum, &pregapsize,
  1781.                 getnum, &defpregap,
  1782.                 &speed,
  1783.                 &load, &eject, &dummy, &msinfo, &toc, &atip,
  1784.                 &multi, &fix, &nofix, &waiti,
  1785.                 &debug, &lverbose, &scsi_verbose,
  1786.                 &audio, &data, &mode2,
  1787.                 &xa1, &xa2, &cdi,
  1788.                 &isize,
  1789.                 &nopreemp, &preemp,
  1790.                 &nopad, &pad, &bswab, getnum, &fs,
  1791.                 getbltype, &bltype, &pktsize,
  1792.                 &ispacket, &noclose, &force,
  1793.                 &dao, &scms,
  1794.                 &isrc, &mcn, &tindex,
  1795.                 &shorttrack, &noshorttrack) < 0) {
  1796.             errmsgno(EX_BAD, "Bad Option: %s.\n", cav[0]);
  1797.             usage(EX_BAD);
  1798.         }
  1799.         if (help)
  1800.             usage(0);
  1801.         if (tracks == 0) {
  1802.             if (driver)
  1803.                 set_cdrcmds(driver, dpp);
  1804.             if (version)
  1805.                 *flagsp |= F_VERSION;
  1806.             if (checkdrive)
  1807.                 *flagsp |= F_CHECKDRIVE;
  1808.             if (prcap)
  1809.                 *flagsp |= F_PRCAP;
  1810.             if (inq)
  1811.                 *flagsp |= F_INQUIRY;
  1812.             if (scanbus)
  1813.                 *flagsp |= F_SCANBUS;
  1814.             if (reset)
  1815.                 *flagsp |= F_RESET;
  1816.             if (ignsize)
  1817.                 *flagsp |= F_IGNSIZE;
  1818.             if (load)
  1819.                 *flagsp |= F_LOAD;
  1820.             if (eject)
  1821.                 *flagsp |= F_EJECT;
  1822.             if (dummy)
  1823.                 *flagsp |= F_DUMMY;
  1824.             if (msinfo)
  1825.                 *flagsp |= F_MSINFO;
  1826.             if (toc) {
  1827.                 *flagsp |= F_TOC;
  1828.                 *flagsp &= ~F_WRITE;
  1829.             }
  1830.             if (atip) {
  1831.                 *flagsp |= F_PRATIP;
  1832.                 *flagsp &= ~F_WRITE;
  1833.             }
  1834.             if (multi) {
  1835.                 *flagsp |= F_MULTI;
  1836.                 tracktype = TOC_XA2;
  1837.                 sectype = ST_ROM_MODE2;
  1838.                 dbtype = DB_XA_MODE2;    /* XXX -multi nimmt DB_XA_MODE2_F1 !!! */
  1839.             }
  1840.             if (fix)
  1841.                 *flagsp |= F_FIX;
  1842.             if (nofix)
  1843.                 *flagsp |= F_NOFIX;
  1844.             if (waiti)
  1845.                 *flagsp |= F_WAITI;
  1846.             if (force) 
  1847.                 *flagsp |= F_FORCE;
  1848.  
  1849.             if (bltype >= 0) {
  1850.                 *flagsp |= F_BLANK;
  1851.                 *blankp = bltype;
  1852.             }
  1853.             if (dao) {
  1854.                 *flagsp |= F_SAO;
  1855.                 trackp[0].flags &= ~TI_TAO;
  1856.             }
  1857.             if (mcn) {
  1858. #ifdef    AUINFO
  1859.                 setmcn(mcn, &trackp[0]);
  1860. #else
  1861.                 trackp[0].isrc = malloc(16);
  1862.                 fillbytes(trackp[0].isrc, 16, '\0');
  1863.                 strncpy(trackp[0].isrc, mcn, 13);
  1864. #endif
  1865.                 mcn = NULL;
  1866.             }
  1867.             version = checkdrive = prcap = inq = scanbus = reset = ignsize =
  1868.             load = eject = dummy = msinfo = toc = atip = multi = fix = nofix =
  1869.             waiti = force = dao = 0;
  1870.         } else if ((version + checkdrive + prcap + inq + scanbus + reset + ignsize +
  1871.                 load + eject + dummy + msinfo + toc + atip + multi + fix + nofix +
  1872.                 waiti + force + dao) > 0 ||
  1873.                 mcn != NULL)
  1874.             comerrno(EX_BAD, "Badly placed option. Global options must be before any track.\n");
  1875.  
  1876.         if (nopreemp)
  1877.             preemp = 0;
  1878.         if (nopad)
  1879.             pad = 0;
  1880.         if (noshorttrack)
  1881.             shorttrack = 0;
  1882.  
  1883.         if ((audio + data + mode2 + xa1 + xa2 + cdi) > 1) {
  1884.             errmsgno(EX_BAD, "Too many types for track %d.\n", tracks+1);
  1885.             comerrno(EX_BAD, "Only one of -audio, -data, -mode2, -xa1, -xa2, -cdi allowed.\n");
  1886.         }
  1887.         if (ispacket && audio) {
  1888.             comerrno(EX_BAD, "Audio data cannot be written in packet mode.\n");
  1889.         }
  1890.         got_track = getfiles(&cac, &cav, opts);
  1891.         if (autoaudio) {
  1892.             autoaudio = 0;
  1893.             tracktype = TOC_ROM;
  1894.             sectype = ST_ROM_MODE1;
  1895.             dbtype = DB_ROM_MODE1;
  1896.         }
  1897.         if (got_track != 0 && (is_auname(cav[0]) || is_wavname(cav[0]))) {
  1898.             autoaudio++;
  1899.             audio++;
  1900.         }
  1901.         if (data) {
  1902.             tracktype = TOC_ROM;
  1903.             sectype = ST_ROM_MODE1;
  1904.             dbtype = DB_ROM_MODE1;
  1905.         }
  1906.         if (mode2) {
  1907.             tracktype = TOC_ROM;
  1908.             sectype = ST_ROM_MODE2;
  1909.             dbtype = DB_ROM_MODE2;
  1910.         }
  1911.         if (audio) {
  1912.             tracktype = TOC_DA;
  1913.             sectype = preemp ? ST_AUDIO_PRE : ST_AUDIO_NOPRE;
  1914.             dbtype = DB_RAW;
  1915.         }
  1916.         if (xa1) {
  1917.             tracktype = TOC_XA1;
  1918.             sectype = ST_ROM_MODE1;
  1919.             dbtype = DB_XA_MODE1;
  1920.         }
  1921.         if (xa2) {
  1922.             tracktype = TOC_XA2;
  1923.             sectype = ST_ROM_MODE2;
  1924.             dbtype = DB_XA_MODE2_F1;    /* XXX Das unterscheidet sich von -multi !!! */
  1925.         }
  1926.         if (cdi) {
  1927.             tracktype = TOC_CDI;
  1928.             sectype = ST_ROM_MODE2;
  1929.             dbtype = DB_XA_MODE2_F1;
  1930.         }
  1931.         if (tracks == 0)
  1932.             *toctypep = tracktype;
  1933.  
  1934.         flags = 0;
  1935.         if ((sectype & ST_AUDIOMASK) != 0)
  1936.             flags |= TI_AUDIO;
  1937.         if (isize) {
  1938.             flags |= TI_ISOSIZE;
  1939.             if ((*flagsp & F_MULTI) != 0)
  1940.                 comerrno(EX_BAD, "Cannot get isosize for multi session disks.\n");
  1941.         }
  1942.         if (preemp)
  1943.             flags |= TI_PREEMP;
  1944.         if (scms)
  1945.             flags |= TI_SCMS;
  1946.  
  1947.         if ((flags & TI_AUDIO) == 0 && padsize > (Llong)0L)
  1948.             pad = TRUE;
  1949.         if (pad) {
  1950.             flags |= TI_PAD;
  1951.             if ((flags & TI_AUDIO) == 0 && padsize == (Llong)0L)
  1952.                 padsize = (Llong)PAD_SIZE;
  1953.         }
  1954.         if (shorttrack && (*flagsp & F_SAO) != 0)
  1955.             flags |= TI_SHORT_TRACK;
  1956.         if (noshorttrack)
  1957.             flags &= ~TI_SHORT_TRACK;
  1958.         if (bswab)
  1959.             flags |= TI_SWAB;
  1960.         if (ispacket) 
  1961.             flags |= TI_PACKET;
  1962.         if (noclose) 
  1963.             flags |= TI_NOCLOSE;
  1964.  
  1965.         if ((*flagsp & F_SAO) == 0)
  1966.             flags |= TI_TAO;
  1967.  
  1968.         if (got_track == 0)
  1969.             break;
  1970.         tracks++;
  1971.  
  1972.         if (tracks > MAX_TRACK)
  1973.             comerrno(EX_BAD, "Track limit (%d) exceeded\n",
  1974.                                 MAX_TRACK);
  1975.  
  1976.         if (strcmp("-", cav[0]) == 0) {
  1977.             trackp[tracks].f = STDIN_FILENO;
  1978.  
  1979. #if    defined(__CYGWIN32__) || defined(__EMX__)
  1980.             setmode(STDIN_FILENO, O_BINARY);
  1981. #endif
  1982.         } else {
  1983.             if (access(cav[0], R_OK) < 0)
  1984.                 comerr("No read access for '%s'.\n", cav[0]);
  1985.  
  1986.             if ((trackp[tracks].f = open(cav[0], O_RDONLY|O_BINARY)) < 0)
  1987.                 comerr("Cannot open '%s'.\n", cav[0]);
  1988.         }
  1989.         if (!is_auname(cav[0]) && !is_wavname(cav[0]))
  1990.             flags |= TI_NOAUHDR;
  1991.  
  1992.         if ((*flagsp & F_SAO) != 0 && (flags & TI_AUDIO) != 0)
  1993.             flags |= TI_PREGAP;    /* Hack for now */
  1994.         if (tracks == 1)
  1995.             flags &= ~TI_PREGAP;
  1996.  
  1997.         if (tracks == 1 && (pregapsize != -1L && pregapsize != 150))
  1998.             pregapsize = -1L;
  1999.         secsize = tracktype == TOC_DA ? AUDIO_SEC_SIZE : DATA_SEC_SIZE;
  2000.         trackp[tracks].filename = cav[0];;
  2001.         trackp[tracks].trackstart = 0L;
  2002.         trackp[tracks].tracksize = tracksize;
  2003.         if (trackp[tracks].pregapsize < 0)
  2004.             trackp[tracks].pregapsize = pregapsize;
  2005.         trackp[tracks+1].pregapsize = -1;
  2006.         trackp[tracks].padsize = padsize;
  2007.         trackp[tracks].secsize = secsize;
  2008.         trackp[tracks].secspt = 0;    /* transfer size is set up in set_trsizes() */
  2009.         trackp[tracks].pktsize = pktsize;
  2010.         trackp[tracks].trackno = tracks;
  2011.         trackp[tracks].sectype = sectype;
  2012.         trackp[tracks].tracktype = tracktype;
  2013.         trackp[tracks].dbtype = dbtype;
  2014.         trackp[tracks].flags = flags;
  2015.         trackp[tracks].nindex = 1;
  2016.         trackp[tracks].tindex = 0;
  2017.         checksize(&trackp[tracks]);
  2018.         tracksize = trackp[tracks].tracksize;
  2019.         if (!is_shorttrk(&trackp[tracks]) &&
  2020.             tracksize > 0 && (tracksize / secsize) < 300) {
  2021.             tracksize = roundup(tracksize, secsize);
  2022.             padsize = tracksize + roundup(padsize, secsize);
  2023.             if ((padsize / secsize) < 300) {
  2024.                 trackp[tracks].padsize =
  2025.                     300 * secsize - tracksize;
  2026.             }
  2027.         }
  2028. #ifdef    AUINFO
  2029.         if (useinfo) {
  2030.             auinfo(cav[0], tracks, trackp);
  2031.             if (tracks == 1)
  2032.                 printf("pregap1: %ld\n", trackp[1].pregapsize);
  2033.         }
  2034. #endif
  2035.         if (isrc) {
  2036. #ifdef    AUINFO
  2037.             setisrc(isrc, &trackp[tracks]);
  2038. #else
  2039.             trackp[tracks].isrc = malloc(16);
  2040.             fillbytes(trackp[tracks].isrc, 16, '\0');
  2041.             strncpy(trackp[tracks].isrc, isrc, 12);
  2042. #endif
  2043.         }
  2044.         if (tindex) {
  2045. #ifdef    AUINFO
  2046.             setindex(tindex, &trackp[tracks]);
  2047. #endif
  2048.         }
  2049.  
  2050.         if (debug) {
  2051.             printf("File: '%s' tracksize: %ld secsize: %d tracktype: %d = %s sectype: %X = %s dbtype: %s flags %X\n",
  2052.                 cav[0], trackp[tracks].tracksize, 
  2053.                 trackp[tracks].secsize, 
  2054.                 tracktype, toc2name[tracktype & TOC_MASK],
  2055.                 sectype, st2name[sectype & ST_MASK], db2name[dbtype], flags);
  2056.         }
  2057.     }
  2058.  
  2059.     if (speed < 0 && speed != -1)
  2060.         comerrno(EX_BAD, "Bad speed option.\n");
  2061.  
  2062.     if (fs < 0L && fs != -1L)
  2063.         comerrno(EX_BAD, "Bad fifo size option.\n");
  2064.  
  2065.     dev = *devp;
  2066.     cdr_defaults(&dev, &speed, &fs);
  2067.     if (debug)
  2068.         printf("dev: %s speed: %d fs: %ld\n", dev, speed, fs);
  2069.  
  2070.     if (speed >= 0)
  2071.         *speedp = speed;
  2072.  
  2073.     if (fs < 0L)
  2074.         fs = DEFAULT_FIFOSIZE;
  2075.  
  2076.     if (dev != *devp && (*flagsp & F_SCANBUS) == 0)
  2077.         *devp = dev;
  2078.  
  2079.     if (!*devp && (*flagsp & (F_VERSION|F_SCANBUS)) == 0) {
  2080.         errmsgno(EX_BAD, "No CD/DVD-Recorder device specified.\n");
  2081.         usage(EX_BAD);
  2082.     }
  2083.     if (*flagsp & (F_LOAD|F_MSINFO|F_TOC|F_PRATIP|F_FIX|F_VERSION|F_CHECKDRIVE|F_PRCAP|F_INQUIRY|F_SCANBUS|F_RESET)) {
  2084.         if (tracks != 0) {
  2085.             errmsgno(EX_BAD, "No tracks allowed with this option\n");
  2086.             usage(EX_BAD);
  2087.         }
  2088.         return;
  2089.     }
  2090.     if (tracks == 0 && (*flagsp & (F_LOAD|F_EJECT|F_BLANK)) == 0) {
  2091.         errmsgno(EX_BAD, "No tracks specified. Need at least one.\n");
  2092.         usage(EX_BAD);
  2093.     }
  2094.     *tracksp = tracks;
  2095.     if (*flagsp & F_SAO) {
  2096.         /*
  2097.          * Make sure that you change WRITER_MAXWAIT & READER_MAXWAIT
  2098.          * too if you change this timeout.
  2099.          */
  2100.         if (*timeoutp < 200)        /* Lead in size is 2:30 */
  2101.             *timeoutp = 200;    /* 200s is 150s *1.33    */
  2102.     }
  2103. }
  2104.  
  2105. LOCAL void
  2106. set_trsizes(dp, tracks, trackp)
  2107.     cdr_t    *dp;
  2108.     int    tracks;
  2109.     track_t    *trackp;
  2110. {
  2111.     int    i;
  2112.  
  2113.     /*
  2114.      * We are using SCSI Group 0 write
  2115.      * and cannot write more than 255 secs at once.
  2116.      */
  2117.     data_secs_per_tr = bufsize/DATA_SEC_SIZE;
  2118.     audio_secs_per_tr = bufsize/AUDIO_SEC_SIZE;
  2119.     data_secs_per_tr = min(255, data_secs_per_tr);
  2120.     audio_secs_per_tr = min(255, audio_secs_per_tr);
  2121.  
  2122.     trackp[1].flags        |= TI_FIRST;
  2123.     trackp[tracks].flags    |= TI_LAST;
  2124.     
  2125.     for (i = 1; i <= tracks; i++) {
  2126.         trackp[i].secspt =
  2127.             is_audio(&trackp[i]) ?
  2128.                 audio_secs_per_tr :
  2129.                 data_secs_per_tr;
  2130.         if (is_packet(&trackp[i]) && trackp[i].pktsize > 0) {
  2131.             if (trackp[i].secspt >= trackp[i].pktsize) {
  2132.                 trackp[i].secspt = trackp[i].pktsize;
  2133.             } else {
  2134.                 comerrno(EX_BAD,
  2135.                     "Track %d packet size %d exceeds buffer limit of %d sectors",
  2136.                     i, trackp[i].pktsize, trackp[i].secspt);
  2137.             }
  2138.         }
  2139.         if ((dp->cdr_flags & CDR_SWABAUDIO) != 0 &&
  2140.                     is_audio(&trackp[i])) {
  2141.             trackp[i].flags ^= TI_SWAB;
  2142.         }
  2143.     }
  2144. }
  2145.  
  2146. EXPORT void
  2147. load_media(scgp, dp, doexit)
  2148.     SCSI    *scgp;
  2149.     cdr_t    *dp;
  2150.     BOOL    doexit;
  2151. {
  2152.     int    code;
  2153.     int    key;
  2154.  
  2155.     /*
  2156.      * Do some preparation before...
  2157.      */
  2158.     scgp->silent++;            /* Be quiet if this fails    */
  2159.     test_unit_ready(scgp);        /* First eat up unit attention    */
  2160.     (*dp->cdr_load)(scgp);        /* now try to load media and    */
  2161.     scsi_start_stop_unit(scgp, 1, 0);/* start unit in silent mode    */
  2162.     scgp->silent--;
  2163.  
  2164.     if (!wait_unit_ready(scgp, 60)) {
  2165.         code = scg_sense_code(scgp);
  2166.         key = scg_sense_key(scgp);
  2167.         scgp->silent++;
  2168.         scsi_prevent_removal(scgp, 0);/* In case someone locked it */
  2169.         scgp->silent--;
  2170.  
  2171.         if (!doexit)
  2172.             return;
  2173.         if (key == SC_NOT_READY && (code == 0x3A || code == 0x30))
  2174.             comerrno(EX_BAD, "No disk / Wrong disk!\n");
  2175.         comerrno(EX_BAD, "CD/DVD-Recorder not ready.\n");
  2176.     }
  2177.  
  2178.     scsi_prevent_removal(scgp, 1);
  2179.     scsi_start_stop_unit(scgp, 1, 0);
  2180.     wait_unit_ready(scgp, 120);
  2181.     scgp->silent++;
  2182.     rezero_unit(scgp);    /* Is this needed? Not supported by some drvives */
  2183.     scgp->silent--;
  2184.     test_unit_ready(scgp);
  2185.     scsi_start_stop_unit(scgp, 1, 0);
  2186.     wait_unit_ready(scgp, 120);
  2187. }
  2188.  
  2189. EXPORT void
  2190. unload_media(scgp, dp, flags)
  2191.     SCSI    *scgp;
  2192.     cdr_t    *dp;
  2193.     int    flags;
  2194. {
  2195.     scsi_prevent_removal(scgp, 0);
  2196.     if ((flags & F_EJECT) != 0)
  2197.         (*dp->cdr_unload)(scgp);
  2198. }
  2199.  
  2200. EXPORT void
  2201. set_secsize(scgp, secsize)
  2202.     SCSI    *scgp;
  2203.     int    secsize;
  2204. {
  2205.     if (secsize > 0) {
  2206.         /*
  2207.          * Try to restore the old sector size.
  2208.          */
  2209.         scgp->silent++;
  2210.         select_secsize(scgp, secsize);
  2211.         scgp->silent--;
  2212.     }
  2213. }
  2214.  
  2215. LOCAL void
  2216. check_recovery(scgp, dp, flags)
  2217.     SCSI    *scgp;
  2218.     cdr_t    *dp;
  2219.     int    flags;
  2220. {
  2221.     if ((*dp->cdr_check_recovery)(scgp)) {
  2222.         errmsgno(EX_BAD, "Recovery needed.\n");
  2223.         unload_media(scgp, dp, flags);
  2224.         excdr(EX_BAD, NULL);    /* XXX &exargs ??? */
  2225.         exit(EX_BAD);
  2226.     }
  2227. }
  2228.  
  2229. #define    DEBUG
  2230. void audioread(scgp, dp, flags)
  2231.     SCSI    *scgp;
  2232.     cdr_t    *dp;
  2233.     int    flags;
  2234. {
  2235. #ifdef    DEBUG
  2236.     int speed = 1;
  2237.     int dummy = 0;
  2238.  
  2239.     if ((*dp->cdr_set_speed_dummy)(scgp, &speed, dummy) < 0)
  2240.         exit(-1);
  2241.     if ((*dp->cdr_set_secsize)(scgp, 2352) < 0)
  2242.         exit(-1);
  2243.     scgp->cap->c_bsize = 2352;
  2244.  
  2245.     read_scsi(scgp, buf, 1000, 1);
  2246.     printf("XXX:\n");
  2247.     write(1, buf, 512);
  2248.     unload_media(scgp, dp, flags);
  2249.     excdr(0, NULL);    /* XXX &exargs ??? */
  2250.     exit(0);
  2251. #endif
  2252. }
  2253.  
  2254. LOCAL void
  2255. print_msinfo(scgp, dp)
  2256.     SCSI    *scgp;
  2257.     cdr_t    *dp;
  2258. {
  2259.     long    off;
  2260.     long    fa;
  2261.  
  2262.     if ((*dp->cdr_session_offset)(scgp, &off) < 0) {
  2263.         errmsgno(EX_BAD, "Cannot read session offset\n");
  2264.         return;
  2265.     }
  2266.     if (lverbose)
  2267.         printf("session offset: %ld\n", off);
  2268.  
  2269.     if (dp->cdr_next_wr_address(scgp, 0, (track_t *)0, &fa) < 0) {
  2270.         errmsgno(EX_BAD, "Cannot read first writable address\n");
  2271.         return;
  2272.     }
  2273.     printf("%ld,%ld\n", off, fa);
  2274. }
  2275.  
  2276. LOCAL void
  2277. print_toc(scgp, dp)
  2278.     SCSI    *scgp;
  2279.     cdr_t    *dp;
  2280. {
  2281.     int    first;
  2282.     int    last;
  2283.     long    lba;
  2284.     long    xlba;
  2285.     struct msf msf;
  2286.     int    adr;
  2287.     int    control;
  2288.     int    mode;
  2289.     int    i;
  2290.  
  2291.     scgp->silent++;
  2292.     if (read_capacity(scgp) < 0) {
  2293.         scgp->silent--;
  2294.         errmsgno(EX_BAD, "Cannot read capacity\n");
  2295.         return;
  2296.     }
  2297.     scgp->silent--;
  2298.     if (read_tochdr(scgp, dp, &first, &last) < 0) {
  2299.         errmsgno(EX_BAD, "Cannot read TOC/PMA\n");
  2300.         return;
  2301.     }
  2302.     printf("first: %d last %d\n", first, last);
  2303.     for (i = first; i <= last; i++) {
  2304.         read_trackinfo(scgp, i, &lba, &msf, &adr, &control, &mode);
  2305.         xlba = -150 +
  2306.             msf.msf_frame + (75*msf.msf_sec) + (75*60*msf.msf_min);
  2307.         if (xlba == lba/4)
  2308.             lba = xlba;
  2309.         print_track(i, lba, &msf, adr, control, mode);
  2310.     }
  2311.     i = 0xAA;
  2312.     read_trackinfo(scgp, i, &lba, &msf, &adr, &control, &mode);
  2313.     xlba = -150 +
  2314.         msf.msf_frame + (75*msf.msf_sec) + (75*60*msf.msf_min);
  2315.     if (xlba == lba/4)
  2316.         lba = xlba;
  2317.     print_track(i, lba, &msf, adr, control, mode);
  2318.     if (lverbose > 1) {
  2319.         scgp->silent++;
  2320.         if (read_cdtext(scgp) < 0)
  2321.             errmsgno(EX_BAD, "No CD-Text or CD-Text unaware drive.\n");
  2322.         scgp->silent++;
  2323.     }
  2324. }
  2325.  
  2326. LOCAL void
  2327. print_track(track, lba, msp, adr, control, mode)
  2328.     int    track;
  2329.     long    lba;
  2330.     struct msf *msp;
  2331.     int    adr;
  2332.     int    control;
  2333.     int    mode;
  2334. {
  2335.     long    lba_512 = lba*4;
  2336.  
  2337.     if (track == 0xAA)
  2338.         printf("track:lout ");
  2339.     else
  2340.         printf("track: %3d ", track);
  2341.  
  2342.     printf("lba: %9ld (%9ld) %02d:%02d:%02d adr: %X control: %X mode: %d\n",
  2343.             lba, lba_512,
  2344.             msp->msf_min,
  2345.             msp->msf_sec,
  2346.             msp->msf_frame,
  2347.             adr, control, mode);
  2348. }
  2349.  
  2350. LOCAL void
  2351. prtimediff(fmt, start, stop)
  2352.     const    char    *fmt;
  2353.     struct timeval    *start;
  2354.     struct timeval    *stop;
  2355. {
  2356.     struct timeval tv;
  2357.  
  2358.     tv.tv_sec = stop->tv_sec - start->tv_sec;
  2359.     tv.tv_usec = stop->tv_usec - start->tv_usec;
  2360.     while (tv.tv_usec > 1000000) {
  2361.         tv.tv_usec -= 1000000;
  2362.         tv.tv_sec += 1;
  2363.     }
  2364.     while (tv.tv_usec < 0) {
  2365.         tv.tv_usec += 1000000;
  2366.         tv.tv_sec -= 1;
  2367.     }
  2368.     /*
  2369.      * We need to cast timeval->* to long because
  2370.      * of the broken sys/time.h in Linux.
  2371.      */
  2372.     printf("%s%4ld.%03lds\n", fmt, (long)tv.tv_sec, (long)tv.tv_usec/1000);
  2373.     flush();
  2374. }
  2375.  
  2376. #ifdef    HAVE_SYS_PRIOCNTL_H
  2377.  
  2378. #include <sys/procset.h>    /* Needed for SCO Openserver */
  2379. #include <sys/priocntl.h>
  2380. #include <sys/rtpriocntl.h>
  2381.  
  2382. EXPORT    void
  2383. raisepri(pri)
  2384.     int pri;
  2385. {
  2386.     int        pid;
  2387.     int        classes;
  2388.     int        ret;
  2389.     pcinfo_t    info;
  2390.     pcparms_t    param;
  2391.     rtinfo_t    rtinfo;
  2392.     rtparms_t    rtparam;
  2393.  
  2394.     pid = getpid();
  2395.  
  2396.     /* get info */
  2397.     strcpy(info.pc_clname, "RT");
  2398.     classes = priocntl(P_PID, pid, PC_GETCID, (void *)&info);
  2399.     if (classes == -1)
  2400.         comerr("Cannot get priority class id priocntl(PC_GETCID)\n");
  2401.  
  2402.     movebytes(info.pc_clinfo, &rtinfo, sizeof(rtinfo_t));
  2403.  
  2404.     /* set priority to max */
  2405.     rtparam.rt_pri = rtinfo.rt_maxpri - pri;
  2406.     rtparam.rt_tqsecs = 0;
  2407.     rtparam.rt_tqnsecs = RT_TQDEF;
  2408.     param.pc_cid = info.pc_cid;
  2409.     movebytes(&rtparam, param.pc_clparms, sizeof(rtparms_t));
  2410.     ret = priocntl(P_PID, pid, PC_SETPARMS, (void *)¶m);
  2411.     if (ret == -1) {
  2412.         errmsg("WARNING: Cannot set priority class parameters priocntl(PC_SETPARMS)\n");
  2413.         errmsgno(EX_BAD, "WARNING: This causes a high risk for buffer underruns.\n");
  2414.     }
  2415. }
  2416.  
  2417. #else    /* HAVE_SYS_PRIOCNTL_H */
  2418.  
  2419. #if defined(_POSIX_PRIORITY_SCHEDULING)
  2420. /*
  2421.  * XXX Ugly but needed because of a typo in /usr/iclude/sched.h on Linux.
  2422.  * XXX This should be removed as soon as we are sure that Linux-2.0.29 is gone.
  2423.  */
  2424. #ifdef    __linux
  2425. #define    _P    __P
  2426. #endif
  2427.  
  2428. #include <sched.h>
  2429.  
  2430. #ifdef    __linux
  2431. #undef    _P
  2432. #endif
  2433.  
  2434. LOCAL    int
  2435. rt_raisepri(pri)
  2436.     int pri;
  2437. {
  2438.     struct sched_param scp;
  2439.  
  2440.     /*
  2441.      * Verify that scheduling is available
  2442.      */
  2443. #ifdef    _SC_PRIORITY_SCHEDULING
  2444.     if (sysconf(_SC_PRIORITY_SCHEDULING) == -1) {
  2445.         errmsg("WARNING: RR-scheduler not available, disabling.\n");
  2446.         return(-1);
  2447.     }
  2448. #endif
  2449.     fillbytes(&scp, sizeof(scp), '\0');
  2450.     scp.sched_priority = sched_get_priority_max(SCHED_RR) - pri;
  2451.     if (sched_setscheduler(0, SCHED_RR, &scp) < 0) {
  2452.         errmsg("WARNING: Cannot set RR-scheduler\n");
  2453.         return (-1);
  2454.     }
  2455.     return (0);
  2456. }
  2457.  
  2458. #else    /* _POSIX_PRIORITY_SCHEDULING */
  2459.  
  2460. #ifdef    __CYGWIN32__
  2461.  
  2462. /*
  2463.  * NOTE: Base.h has a second typedef for BOOL.
  2464.  *     We define BOOL to make all local code use BOOL
  2465.  *     from Windows.h and use the hidden __SBOOL for
  2466.  *     our global interfaces.
  2467.  */
  2468. #define    BOOL    WBOOL        /* This is the Win BOOL        */
  2469. #define    format    __format
  2470. #include <vadefs.h>
  2471. #include <Windows32/Base.h>
  2472. #include <Windows32/Defines.h>
  2473. #include <Windows32/Structures.h>
  2474. #include <Windows32/Functions.h>
  2475. #undef format
  2476.  
  2477. LOCAL    int
  2478. rt_raisepri(pri)
  2479.     int pri;
  2480. {
  2481.     /* set priority class */
  2482.     if (SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS) == FALSE) {
  2483.         errmsgno(EX_BAD, "No realtime priority class possible.\n");
  2484.         return (-1);
  2485.     }
  2486.  
  2487.     /* set thread priority */
  2488.     if (SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL-pri) == FALSE) {
  2489.         errmsgno(EX_BAD, "Could not set realtime priority.\n");
  2490.         return (-1);
  2491.     }
  2492.     return (0);
  2493. }
  2494.  
  2495. #else
  2496.  
  2497. LOCAL    int
  2498. rt_raisepri(pri)
  2499.     int pri;
  2500. {
  2501.     return (-1);
  2502. }
  2503.  
  2504. #endif    /* __CYGWIN32__ */
  2505.  
  2506. #endif    /* _POSIX_PRIORITY_SCHEDULING */
  2507.  
  2508. EXPORT    void
  2509. raisepri(pri)
  2510.     int pri;
  2511. {
  2512.     if (rt_raisepri(pri) >= 0)
  2513.         return;
  2514. #if    defined(HAVE_SETPRIORITY) && defined(PRIO_PROCESS)
  2515.  
  2516.     if (setpriority(PRIO_PROCESS, getpid(), -20 + pri) < 0) {
  2517.         errmsg("WARNING: Cannot set priority using setpriority().\n");
  2518.         errmsgno(EX_BAD, "WARNING: This causes a high risk for buffer underruns.\n");
  2519.     }
  2520. #else
  2521. #ifdef    HAVE_DOSSETPRIORITY    /* RT priority on OS/2 */
  2522.     /*
  2523.      * Set priority to timecritical 31 - pri (arg)
  2524.      */
  2525.     DosSetPriority(0, 3, 31, 0);
  2526.     DosSetPriority(0, 3, -pri, 0);
  2527. #else
  2528. #ifdef    HAVE_NICE
  2529.     if (nice(-20 + pri) == -1) {
  2530.         errmsg("WARNING: Cannot set priority using nice().\n");
  2531.         errmsgno(EX_BAD, "WARNING: This causes a high risk for buffer underruns.\n");
  2532.     }
  2533. #else
  2534.     errmsgno(EX_BAD, "WARNING: Cannot set priority on this OS.\n");
  2535.     errmsgno(EX_BAD, "WARNING: This causes a high risk for buffer underruns.\n");
  2536. #endif
  2537. #endif
  2538. #endif
  2539. }
  2540.  
  2541. #endif    /* HAVE_SYS_PRIOCNTL_H */
  2542.  
  2543. #ifdef    HAVE_SELECT
  2544. /*
  2545.  * sys/types.h and sys/time.h are already included.
  2546.  */
  2547. #else
  2548. #    include    <stropts.h>
  2549. #    include    <poll.h>
  2550.  
  2551. #ifndef    INFTIM
  2552. #define    INFTIM    (-1)
  2553. #endif
  2554. #endif
  2555.  
  2556. #if    defined(HAVE_SELECT) && defined(NEED_SYS_SELECT_H)
  2557. #include <sys/select.h>
  2558. #endif
  2559.  
  2560. LOCAL void
  2561. wait_input()
  2562. {
  2563. #ifdef    HAVE_SELECT
  2564.     fd_set    in;
  2565.  
  2566.     FD_ZERO(&in);
  2567.     FD_SET(STDIN_FILENO, &in);
  2568.     select(1, &in, NULL, NULL, 0);
  2569. #else
  2570.     struct pollfd pfd;
  2571.  
  2572.     pfd.fd = STDIN_FILENO;
  2573.     pfd.events = POLLIN;
  2574.     pfd.revents = 0;
  2575.     poll(&pfd, (unsigned long)1, INFTIM);
  2576. #endif
  2577. }
  2578.  
  2579. LOCAL void
  2580. checkgui()
  2581. {
  2582.     struct stat st;
  2583.  
  2584.     if (fstat(STDERR_FILENO, &st) >= 0 && !S_ISCHR(st.st_mode)) {
  2585.         isgui = TRUE;
  2586.         if (lverbose > 1)
  2587.             printf("Using remote (pipe) mode for interactive i/o.\n");
  2588.     }
  2589. }
  2590.  
  2591. LOCAL char *
  2592. astoll(s, ll)
  2593.     register const char *s;
  2594.         Llong *ll;
  2595. {
  2596.     char    *p;
  2597.     long    l = 0;
  2598.  
  2599.     p = astol(s, &l);
  2600.     *ll = (Llong)l;
  2601.     return (p);
  2602. }
  2603.  
  2604. LOCAL Llong
  2605. number(arg, retp)
  2606.     register char    *arg;
  2607.         int    *retp;
  2608. {
  2609.     Llong    val    = 0;
  2610.  
  2611.     if (*retp != 1)
  2612.         return (val);
  2613.     if (*arg == '\0') {
  2614.         *retp = -1;
  2615.     } else if (*(arg = astoll(arg, &val))) {
  2616.         if (*arg == 'p' || *arg == 'P') {
  2617.             val *= (1024*1024);
  2618.             val *= (1024*1024*1024);
  2619.             arg++;
  2620.         }
  2621.         if (*arg == 't' || *arg == 'T') {
  2622.             val *= (1024*1024);
  2623.             val *= (1024*1024);
  2624.             arg++;
  2625.         }
  2626.         if (*arg == 'g' || *arg == 'G') {
  2627.             val *= (1024*1024*1024);
  2628.             arg++;
  2629.         }
  2630.         if (*arg == 'm' || *arg == 'M') {
  2631.             val *= (1024*1024);
  2632.             arg++;
  2633.         }
  2634.         else if (*arg == 'f' || *arg == 'F') {
  2635.             val *= 2352;
  2636.             arg++;
  2637.         }
  2638.         else if (*arg == 's' || *arg == 'S') {
  2639.             val *= 2048;
  2640.             arg++;
  2641.         }
  2642.         else if (*arg == 'k' || *arg == 'K') {
  2643.             val *= 1024;
  2644.             arg++;
  2645.         }
  2646.         else if (*arg == 'b' || *arg == 'B') {
  2647.             val *= 512;
  2648.             arg++;
  2649.         }
  2650.         else if (*arg == 'w' || *arg == 'W') {
  2651.             val *= 2;
  2652.             arg++;
  2653.         }
  2654.         if (*arg == '*' || *arg == 'x')
  2655.             val *= number(++arg, retp);
  2656.         else if (*arg != '\0')
  2657.             *retp = -1;
  2658.     }
  2659.     return (val);
  2660. }
  2661.  
  2662. EXPORT int
  2663. getnum(arg, valp)
  2664.     char    *arg;
  2665.     long    *valp;
  2666. {
  2667.     int    ret = 1;
  2668.  
  2669.     *valp = (long)number(arg, &ret);
  2670.     return (ret);
  2671. }
  2672.  
  2673. EXPORT int
  2674. getllnum(arg, lvalp)
  2675.     char    *arg;
  2676.     Llong    *lvalp;
  2677. {
  2678.     int    ret = 1;
  2679.  
  2680.     *lvalp = number(arg, &ret);
  2681.     return (ret);
  2682. }
  2683.  
  2684. LOCAL int
  2685. getbltype(optstr, typep)
  2686.     char    *optstr;
  2687.     long    *typep;
  2688. {
  2689.     if (streql(optstr, "all")) {
  2690.         *typep = BLANK_DISC;
  2691.     } else if (streql(optstr, "disc")) {
  2692.         *typep = BLANK_DISC;
  2693.     } else if (streql(optstr, "disk")) {
  2694.         *typep = BLANK_DISC;
  2695.     } else if (streql(optstr, "fast")) {
  2696.         *typep = BLANK_MINIMAL;
  2697.     } else if (streql(optstr, "minimal")) {
  2698.         *typep = BLANK_MINIMAL;
  2699.     } else if (streql(optstr, "track")) {
  2700.         *typep = BLANK_TRACK;
  2701.     } else if (streql(optstr, "unreserve")) {
  2702.         *typep = BLANK_UNRESERVE;
  2703.     } else if (streql(optstr, "trtail")) {
  2704.         *typep = BLANK_TAIL;
  2705.     } else if (streql(optstr, "unclose")) {
  2706.         *typep = BLANK_UNCLOSE;
  2707.     } else if (streql(optstr, "session")) {
  2708.         *typep = BLANK_SESSION;
  2709.     } else if (streql(optstr, "help")) {
  2710.         blusage(0);
  2711.     } else {
  2712.         error("Illegal blanking type '%s'.\n", optstr);
  2713.         blusage(EX_BAD);
  2714.         return (-1);
  2715.     }
  2716.     return (TRUE);
  2717. }
  2718.